Add board k210-emulator

This commit is contained in:
Zhao_Jiasheng 2021-05-10 21:08:25 +08:00
parent 0602e09627
commit 6f7cf059ec
106 changed files with 28284 additions and 3 deletions

View File

@ -5,7 +5,7 @@ MAKEFLAGS += --no-print-directory
.PHONY:COMPILE_APP COMPILE_KERNEL
support :=kd233 stm32f407-st-discovery maix-go stm32f407zgt6 aiit-riscv64-board aiit-arm32-board hifive1-rev-B hifive1-emulator
support :=kd233 stm32f407-st-discovery maix-go stm32f407zgt6 aiit-riscv64-board aiit-arm32-board hifive1-rev-B hifive1-emulator k210-emulator
SRC_DIR:=
export BOARD ?=kd233

View File

@ -49,7 +49,9 @@ _begin:
li t0, MSTATUS_FS
csrs mstatus, t0
#ifndef BSP_USING_QEMU
ZERO_F_REGISTERS
#endif
.option push
.option norelax

View File

@ -42,10 +42,15 @@ int InitHwTick(void)
CLEAR_CSR(mie, MIP_MTIP);
#ifdef BSP_USING_QEMU
tick_cycles = (10000000 / TICK_PER_SECOND);
#else
tick_cycles = interval * SysctlClockGetFreq(SYSCTL_CLOCK_CPU) / CLINT_CLOCK_DIV / 1000ULL - 1;
#endif
clint->mtimecmp[core_id] = clint->mtime + tick_cycles;
SET_CSR(mie, MIP_MTIP);
return 0;
}
}

View File

@ -0,0 +1,238 @@
#
# Automatically generated file; DO NOT EDIT.
# XiUOS Project Configuration
#
CONFIG_BOARD_K210_EVB=y
CONFIG_KERNEL_CONSOLE_DEVICE_NAME="uarths"
CONFIG_LED0=24
CONFIG_LED1=25
CONFIG_ARCH_CPU_64BIT=y
CONFIG_ARCH_RISCV=y
CONFIG_ARCH_RISCV64=y
#
# kd233 feature
#
# CONFIG_BSP_USING_AUDIO is not set
# CONFIG_BSP_USING_CAMERA is not set
# CONFIG_BSP_USING_SDIO is not set
CONFIG_BSP_USING_DMA=y
CONFIG_BSP_USING_GPIO=y
# CONFIG_BSP_USING_I2C is not set
# CONFIG_BSP_USING_I2S is not set
# CONFIG_BSP_USING_LCD is not set
# CONFIG_BSP_USING_RTC is not set
# CONFIG_BSP_USING_SECURITY is not set
# CONFIG_BSP_USING_SPI is not set
CONFIG_BSP_USING_UART=y
CONFIG_BSP_USING_UART_HS=y
# CONFIG_BSP_USING_VIDEO is not set
# CONFIG_BSP_USING_WDT is not set
#
# General Purpose UARTs
#
CONFIG_BSP_USING_UART1=y
CONFIG_BSP_UART1_TXD_PIN=20
CONFIG_BSP_UART1_RXD_PIN=21
CONFIG_BSP_USING_UART2=y
CONFIG_BSP_UART2_TXD_PIN=28
CONFIG_BSP_UART2_RXD_PIN=27
CONFIG_BSP_USING_UART3=y
CONFIG_BSP_UART3_TXD_PIN=22
CONFIG_BSP_UART3_RXD_PIN=23
CONFIG___STACKSIZE__=4096
#
# Hardware feature
#
CONFIG_RESOURCES_SERIAL=y
# CONFIG_SERIAL_USING_DMA is not set
# CONFIG_SERIAL_RB_BUFSZ is not set
# CONFIG_RESOURCES_HWTIMER is not set
# CONFIG_RESOURCES_I2C is not set
# CONFIG_RESOURCES_LCD is not set
# CONFIG_RESOURCES_SDIO is not set
# CONFIG_RESOURCES_TOUCH is not set
CONFIG_RESOURCES_PIN=y
# CONFIG_RESOURCES_RTC is not set
# CONFIG_RESOURCES_SPI is not set
#CONFIG_RESOURCES_SPI_SD is not set
#CONFIG_RESOURCES_SPI_SFUD is not set
# SFUD_USING_SFDP is not set
# SFUD_USING_FLASH_INFO_TABLE is not set
# SFUD_DEBUG_LOG is not set
# CONFIG_RESOURCES_WDT is not set
# CONFIG_RESOURCES_USB is not set
# CONFIG_RESOURCES_USB_HOST is not set
# CONFIG_UDISK_MOUNTPOINT is not set
# CONFIG_USBH_MSTORAGE is not set
# CONFIG_RESOURCES_USB_DEVICE is not set
# CONFIG_USBD_THREAD_STACK_SZ is not set
#
# Kernel feature
#
# CONFIG_SEPARATE_COMPILE is not set
# CONFIG_COMPILER_APP is not set
# CONFIG_COMPILER_KERNEL is not set
#
# Kernel Device Object
#
CONFIG_KERNEL_DEVICE=y
CONFIG_KERNEL_CONSOLE=y
CONFIG_KERNEL_CONSOLEBUF_SIZE=128
#
# Task feature
#
CONFIG_SCHED_POLICY_RR_REMAINSLICE=y
# CONFIG_SCHED_POLICY_RR is not set
# CONFIG_SCHED_POLICY_FIFO is not set
#
# Inter-Task communication
#
CONFIG_KERNEL_SEMAPHORE=y
CONFIG_KERNEL_MUTEX=y
CONFIG_KERNEL_EVENT=y
CONFIG_KERNEL_MESSAGEQUEUE=y
# CONFIG_KTASK_PRIORITY_8 is not set
CONFIG_KTASK_PRIORITY_32=y
# CONFIG_KTASK_PRIORITY_256 is not set
CONFIG_KTASK_PRIORITY_MAX=32
CONFIG_TICK_PER_SECOND=100
CONFIG_KERNEL_STACK_OVERFLOW_CHECK=y
CONFIG_KERNEL_BANNER=y
# CONFIG_KERNEL_HOOK is not set
CONFIG_KERNEL_SOFTTIMER=y
CONFIG_KERNEL_IDLE_HOOK=y
CONFIG_IDEL_HOOK_LIST_SIZE=4
CONFIG_IDLE_KTASK_STACKSIZE=1024
CONFIG_USER_APPLICATION=y
# CONFIG_TASK_ISOLATION is not set
#
# Memory Management
#
# CONFIG_KERNEL_MEMBLOCK is not set
#
# Command shell
#
CONFIG_TOOL_SHELL=y
CONFIG_SHELL_TASK_PRIORITY=20
CONFIG_SHELL_TASK_STACK_SIZE=4096
#
# User Control
#
CONFIG_SHELL_DEFAULT_USER="letter"
CONFIG_SHELL_DEFAULT_USER_PASSWORD=""
CONFIG_SHELL_LOCK_TIMEOUT=10000
CONFIG_SHELL_ENTER_CR_AND_LF=y
# CONFIG_SHELL_ENTER_CRLF is not set
CONFIG_SHELL_ENTER_CR=y
CONFIG_SHELL_ENTER_LF=y
CONFIG_SHELL_MAX_NUMBER=5
CONFIG_SHELL_PARAMETER_MAX_NUMBER=8
CONFIG_SHELL_HISTORY_MAX_NUMBER=5
CONFIG_SHELL_PRINT_BUFFER=128
CONFIG_SHELL_USING_CMD_EXPORT=y
# CONFIG_SHELL_HELP_LIST_USER is not set
CONFIG_SHELL_HELP_SHOW_PERMISSION=y
# CONFIG_SHELL_HELP_LIST_VAR is not set
# CONFIG_SHELL_HELP_LIST_KEY is not set
CONFIG_KERNEL_QUEUEMANAGE=y
CONFIG_KERNEL_WORKQUEUE=y
CONFIG_WORKQUEUE_KTASK_STACKSIZE=512
CONFIG_WORKQUEUE_KTASK_PRIORITY=23
CONFIG_KERNEL_WAITQUEUE=y
CONFIG_KERNEL_DATAQUEUE=y
# CONFIG_KERNEL_CIRCULAR_AREA is not set
# CONFIG_KERNEL_AVL_TREE is not set
CONFIG_NAME_MAX=32
CONFIG_ALIGN_SIZE=8
CONFIG_KERNEL_COMPONENTS_INIT=y
CONFIG_KERNEL_USER_MAIN=y
CONFIG_MAIN_KTASK_STACK_SIZE=2048
CONFIG_ENV_INIT_KTASK_STACK_SIZE=8192
CONFIG_MAIN_KTASK_PRIORITY=10
# CONFIG_USER_TEST is not set
# CONFIG_TOOL_TEST_SEM is not set
# CONFIG_TOOL_TEST_MUTEX is not set
# CONFIG_TOOL_TEST_EVENT is not set
# CONFIG_TOOL_TEST_MSG is not set
# CONFIG_TOOL_TEST_AVLTREE is not set
# CONFIG_TEST_CRICULAR_AREA is not set
# CONFIG_TOOL_TEST_MEM is not set
# CONFIG_TOOL_TEST_TIMER is not set
# CONFIG_TOOL_TEST_IWG is not set
# CONFIG_TOOL_TEST_REALTIME is not set
# CONFIG_TOOL_TEST_DBG is not set
# CONFIG_TOOL_TEST_SCHED is not set
# CONFIG_KERNEL_DEBUG is not set
CONFIG_DEBUG_INIT_CONFIG=y
CONFIG_DBG_INIT=1
CONFIG_ARCH_SMP=y
CONFIG_CPUS_NR=2
#
# File system
#
CONFIG_FS_VFS=y
CONFIG_VFS_USING_WORKDIR=y
CONFIG_FS_VFS_DEVFS=y
#
# Fat filesystem
#
#
# IOT-Device File system
#
#
# Lwext4 filesystem
#
#
# APP Framework
#
#
# Perception
#
# CONFIG_PERCEPTION_SENSORDEVICE is not set
#
# connection
#
# CONFIG_CONNECTION_AT is not set
# CONFIG_CONNECTION_MQTT is not set
#
# medium communication
#
#
# Intelligence
#
#
# Control
#
#
# Lib
#
CONFIG_LIB=y
CONFIG_LIB_POSIX=y
CONFIG_LIB_NEWLIB=y
CONFIG_LITTLEVGL2RTT_USING_DEMO=y
#
# Security
#

View File

@ -0,0 +1,81 @@
mainmenu "XiUOS Project Configuration"
config BSP_DIR
string
option env="BSP_ROOT"
default "."
config KERNEL_DIR
string
option env="KERNEL_ROOT"
default "../.."
config BOARD_K210_EVB
bool
select ARCH_RISCV
select ARCH_RISCV64
select ARCH_CPU_64BIT
default y
config LED0
int
default 24
config LED1
int
default 25
source "$KERNEL_DIR/arch/Kconfig"
menu "kd233 feature"
source "$BSP_DIR/third_party_driver/Kconfig"
menu "config default board resources"
menu "config board app name"
config BOARD_APP_NAME
string "config board app name"
default "/XiUOS_kd233_app.bin"
endmenu
menu "config board service table"
config SERVICE_TABLE_ADDRESS
hex "board service table address"
default 0x80100000
endmenu
menu "config hardware resources for connection"
if CONNECTION_COMMUNICATION_ETHERNET
config ETHERNET_UART_NAME
string "ethernet uart name"
default "/dev/uart3_dev3"
endif
if CONNECTION_COMMUNICATION_WIFI
config WIFI_UART_NAME
string "wifi uart name"
default "/dev/uart3_dev3"
endif
endmenu
endmenu
config __STACKSIZE__
int "stack size for interrupt"
default 4096
endmenu
config BSP_USING_QEMU
bool
default y
menu "Hardware feature"
source "$KERNEL_DIR/resources/Kconfig"
endmenu
source "$KERNEL_DIR/Kconfig"

View File

@ -0,0 +1,6 @@
SRC_FILES := board.c
SRC_DIR := third_party_driver
include $(KERNEL_ROOT)/compiler.mk

View File

@ -0,0 +1,164 @@
# 从零开始构建矽璓工业物联操作系统使用risc-v架构的k210 emulator
# k210 emulator
[XiUOS](http://xuos.io/) (X Industrial Ubiquitous Operating System) 矽璓XiUOS是一款面向智慧车间的工业物联网操作系统主要由一个极简的微型实时操作系统内核和其上的工业物联框架构成通过高效管理工业物联网设备、支撑工业物联应用在生产车间内实现智能化的“感知环境、联网传输、知悉识别、控制调整”促进以工业设备和工业控制系统为核心的人、机、物深度互联帮助提升生产线的数字化和智能化水平。
>注最新版README请访问[从零开始构建矽璓工业物联操作系统使用risc-v架构的k210 emulator](https://blog.csdn.net/AIIT_Ubiquitous/article/details/116610203),如博客内容与本地文档有差异,以网站内容为准。
## 1. 简介
QEMU 是一个通用的开源模拟器和虚拟化工具。从5.0版本开始QEMU已经可以较完整的支持RISC-V架构。目前XiUOS同样支持运行在QEMU上
| 硬件 | 描述 |
| -- | -- |
|芯片型号| K210 |
|架构| 双核RV64GC |
|主频| 400MHz |
|片内SRAM| 8MB |
| 外设支持 | UART |
XiUOS板级当前支持使用UART。
## 2. 编译说明
**操作系统:** ubuntu18.04 [https://ubuntu.com/download/desktop](https://ubuntu.com/download/desktop)
**开发工具推荐使用 VSCode VScode下载地址为** VSCode [https://code.visualstudio.com/](https://code.visualstudio.com/),推荐下载地址为 [http://vscode.cdn.azure.cn/stable/3c4e3df9e89829dce27b7b5c24508306b151f30d/code_1.55.2-1618307277_amd64.deb](http://vscode.cdn.azure.cn/stable/3c4e3df9e89829dce27b7b5c24508306b151f30d/code_1.55.2-1618307277_amd64.deb)
### 依赖包安装:
```
$ sudo apt install build-essential pkg-config
$ sudo apt install gcc make libncurses5-dev openssl libssl-dev bison flex libelf-dev autoconf libtool gperf libc6-dev git
```
**XiUOS操作系统源码下载** XiUOS [https://forgeplus.trustie.net/projects/xuos/xiuos](https://forgeplus.trustie.net/projects/xuos/xiuos)
新建一个空文件夹并进入文件夹中,并下载源码,具体命令如下:
```c
mkdir test && cd test
git clone https://git.trustie.net/xuos/xiuos.git
```
打开源码文件包可以看到以下目录:
| 名称 | 说明 |
| -- | -- |
| application | 应用代码 |
| board | 板级支持包 |
| framework | 应用框架 |
| fs | 文件系统 |
| kernel | 内核源码 |
| resources | 驱动文件 |
| tool | 系统工具 |
使用VScode打开代码具体操作步骤为在源码文件夹下打开系统终端输入`code .`即可打开VScode开发环境如下图所示
![vscode](img/vscode.jpg)
### 裁减配置工具的下载
**裁减配置工具:** kconfig-frontends [https://forgeplus.trustie.net/projects/xuos/kconfig-frontends](https://forgeplus.trustie.net/projects/xuos/kconfig-frontends)
执行以下命令下载配置工具:
```c
mkdir kfrontends && cd kfrontends
git clone https://git.trustie.net/xuos/kconfig-frontends.git
```
下载源码后按以下步骤执行软件安装:
```c
cd kconfig-frontends
./xs_build.sh
```
### 编译工具链:
RISC-V: riscv-none-embed-默认安装到Ubuntu的/opt/,下载源码并解压。[下载网址 http://101.36.126.201:8011/gnu-mcu-eclipse.tar.bz2](http://101.36.126.201:8011/gnu-mcu-eclipse.tar.bz2),下载完成后,执行以下命令:
```c
sudo tar -xvjf gnu-mcu-eclipse.tar.bz2 -C /opt/
```
在VScode中将上述解压的编译工具链的路径添加到board/k210-emulator/config.mk文件当中操作如下
```c
export CROSS_COMPILE ?=/opt/gnu-mcu-eclipse/riscv-none-gcc/8.2.0-2.1-20190425-1021/bin/riscv-none-embed-
```
若`CROSS_COMPILE ` 变量定义语句已经存在,将它替换成上面的语句
# 编译步骤:
1.在`VScode`的“命令终端”中执行以下命令,生成配置文件
```
make BOARD=k210-emulator menuconfig
```
2.在menuconfig界面配置需要关闭和开启的功能按回车键进入下级菜单按Y键选中需要开启的功能按N键选中需要关闭的功能配置结束后选择Exit保存并退出本例旨在演示简单的输出例程所以没有需要配置的选项双击快捷键ESC退出配置
![menuconfig1](img/menuconfig1.png)
退出时选择`yes`保存上面所配置的内容,如下图所示:
![menuconfig2](img/menuconfig2.png)
若执行 `make BOARD=k210-emulator menuconfig`后出现以下界面:
![menuconfig3](img/menuconfig3.png)
解决的方法是将终端向上拉伸超过当前界面的三分之二以上,效果如下:
![menuconfig4](img/menuconfig4.png)
3.继续在VScode命令终端中执行以下命令进行编译
```c
make BOARD=k210-emulator
```
4.如果编译正确无误会在build目录下产生XiUOS_k210-emulator.elf、XiUOS_k210-emulator.bin文件。
## 3. 运行
### 3.1 编译并安装QEMU
**QEMU v6.0.0源码下载:** Qemu-K210 Emulator for XiUOS [https://forgeplus.trustie.net/projects/xuos/QemuK210](https://forgeplus.trustie.net/projects/xuos/QemuK210)
```
git clone https://git.trustie.net/xuos/QemuK210.git
sudo apt install ninja-build libpixman-1-dev
cd QemuK210
./configure --target-list=riscv64-softmmu
make
sudo make install
```
### 3.2 运行结果
通过以下命令启动QEMU并加载XiUOS ELF文件
```
qemu-system-riscv64 -nographic -machine sifive_u -bios build/XiUOS_k210-emulator.elf
```
QEMU运行起来后将会在终端上看到信息打印输出
![terminal](img/terminal.png)
### 3.3 调试
利用QEMU可以方便的对XiUOS进行调试首先通过以下命令启动QEMU
```
qemu-system-riscv64 -nographic -machine sifive_u -bios build/XiUOS_k210-emulator.elf -s -S
```
然后要重新开启另一个linux系统终端一个终端执行`riscv-none-embed-gdb`命令
```
riscv-none-embed-gdb build/XiUOS_k210-emulator.elf -ex "target remote localhost:1234"
```

207
board/k210-emulator/board.c Normal file
View File

@ -0,0 +1,207 @@
/* Copyright 2018 Canaan Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* @file board.c
* @brief support kd233-board init configure and start-up
* @version 1.0
* @author AIIT XUOS Lab
* @date 2021-04-25
*/
/*************************************************
File name: board.c
Description: support kd233-board init configure and driver/task/... init
Others: https://canaan-creative.com/developer
History:
1. Date: 2021-04-25
Author: AIIT XUOS Lab
Modification:
1. support kd233-board InitBoardHardware
2. support kd233-board Kd233Start
3. support kd233-board shell cmd, include reboot, shutdown
*************************************************/
#include <xiuos.h>
#include <clint.h>
#include <sysctl.h>
#include "board.h"
#include "tick.h"
#include "connect_uart.h"
#include "encoding.h"
#include "fpioa.h"
#include "dmac.h"
#include "connect_gpio.h"
#if defined(FS_VFS)
#include <iot-vfs.h>
#endif
#define CPU0 (0)
#define CPU1 (1)
extern x_base cpu2_boot_flag;
extern void entry(void);
extern void SecondaryCpuCStart(void);
extern void ShutdownCpu(void);
extern int IoConfigInit(void);
extern int HwSpiInit(void);
extern int HwI2cInit(void);
extern int HwRtcInit(void);
extern int HwWdtInit(void);
extern int HwLcdInit(void);
extern int HwTimerInit(void);
void InitBss(void)
{
unsigned int *dst;
dst = &__bss_start;
while (dst < &__bss_end){
*dst++ = 0;
}
}
void Kd233Start(uint32_t mhartid)
{
switch(mhartid) {
case CPU0:
InitBss();
/*kernel start entry*/
entry();
break;
#ifdef ARCH_SMP
case CPU1:
while(0x2018050420191010 != cpu2_boot_flag) { ///< waiting for boot flag ,then start cpu1 core
}
SecondaryCpuCStart();
break;
#endif
default:
break;
}
}
int Freq(void)
{
uint64 value = 0;
value = SysctlClockGetFreq(SYSCTL_CLOCK_PLL0);
KPrintf("PLL0: %d\n", value);
value = SysctlClockGetFreq(SYSCTL_CLOCK_PLL1);
KPrintf("PLL1: %d\n", value);
value = SysctlClockGetFreq(SYSCTL_CLOCK_PLL2);
KPrintf("PLL2: %d\n", value);
value = SysctlClockGetFreq(SYSCTL_CLOCK_CPU);
KPrintf("CPU : %d\n", value);
value = SysctlClockGetFreq(SYSCTL_CLOCK_APB0);
KPrintf("APB0: %d\n", value);
value = SysctlClockGetFreq(SYSCTL_CLOCK_APB1);
KPrintf("APB1: %d\n", value);
value = SysctlClockGetFreq(SYSCTL_CLOCK_APB2);
KPrintf("APB2: %d\n", value);
value = SysctlClockGetFreq(SYSCTL_CLOCK_HCLK);
KPrintf("HCLK: %d\n", value);
value = clint_get_time();
KPrintf("mtime: %d\n", value);
return 0;
}
SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0)|SHELL_CMD_TYPE(SHELL_TYPE_CMD_FUNC)|SHELL_CMD_PARAM_NUM(0),freq, Freq, show freq info );
#ifdef ARCH_SMP
extern int EnableHwclintIpi(void);
#endif
struct InitSequenceDesc _board_init[] =
{
#ifdef BSP_USING_GPIO
{ "hw_pin", HwGpioInit },
#endif
#ifdef BSP_USING_HWTIMER
{ "hw_timer" , HwTimerInit },
#endif
{ " NONE ",NONE },
};
void InitBoardHardware(void)
{
int i = 0;
int ret = 0;
/* initalize interrupt */
InitHwinterrupt();
#ifdef BSP_USING_UART
HwUartInit();
#endif
#ifdef KERNEL_CONSOLE
/* set console device */
InstallConsole(KERNEL_CONSOLE_BUS_NAME, KERNEL_CONSOLE_DRV_NAME, KERNEL_CONSOLE_DEVICE_NAME);
KPrintf("\nconsole init completed.\n");
KPrintf("board initialization......\n");
#endif /* KERNEL_CONSOLE */
InitHwTick();
#ifdef ARCH_SMP
EnableHwclintIpi();
#endif
/* initialize memory system */
InitBoardMemory(MEMORY_START_ADDRESS, MEMORY_END_ADDRESS);
#ifdef KERNEL_COMPONENTS_INIT
for(i = 0; _board_init[i].fn != NONE; i++) {
ret = _board_init[i].fn();
KPrintf("initialize %s %s\n",_board_init[i].fn_name, ret == 0 ? "success" : "failed");
}
#endif
KPrintf("board init done.\n");
KPrintf("start kernel...\n");
}
void HwCpuReset(void)
{
sysctl->soft_reset.soft_reset = 1;
while(RET_TRUE);
}
SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0)|SHELL_CMD_TYPE(SHELL_TYPE_CMD_FUNC)|SHELL_CMD_PARAM_NUM(0),
reboot, HwCpuReset, reset machine );
static void (*pre_shutdown_action)(void *);
static void *pre_shutdown_action_arg;
void SetPreShutdownAction(void (*func)(void *), void *arg)
{
pre_shutdown_action = func;
pre_shutdown_action_arg = arg;
}
void CmdShutdown()
{
#ifdef FS_VFS
SyncOpenedFiles();
#endif
if (pre_shutdown_action != NULL)
pre_shutdown_action(pre_shutdown_action_arg);
ShutdownCpu();
}
SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0)|SHELL_CMD_TYPE(SHELL_TYPE_CMD_FUNC)|SHELL_CMD_PARAM_NUM(0),
shutdown,CmdShutdown,shutdown machine);

View File

@ -0,0 +1,91 @@
/* Copyright 2018 Canaan Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* @file board.h
* @brief define kd233-board init configure and start-up function
* @version 1.0
* @author AIIT XUOS Lab
* @date 2021-04-25
*/
/*************************************************
File name: board.h
Description: define kd233-board board init function and struct
Others: https://canaan-creative.com/developer
History:
1. Date: 2021-04-25
Author: AIIT XUOS Lab
Modification:
1. define kd233-board InitBoardHardware
2. define kd233-board data and bss struct
*************************************************/
#ifndef BOARD_H__
#define BOARD_H__
#include <xsconfig.h>
#include <stdint.h>
// #include "../../kernel/include/xs_service.h"
extern unsigned int __bss_start;
extern unsigned int __bss_end;
extern unsigned int __stack_end__;
extern unsigned int g_service_table_start;
extern unsigned int g_service_table_end;
#ifdef SEPARATE_COMPILE
#define G_SERVICE_TABLE_LENGTH (0x1000)
#define MEMORY_START_ADDRESS (void*)&__stack_end__
#define MEMORY_END_ADDRESS (void*)((0x80000000 + 1 * 1024 * 1024)) /* 1M SRAM */
typedef int (*main_t)(int argc, char *argv[]);
typedef void (*exit_t)(void);
struct UserSpaceS
{
main_t us_entrypoint;
exit_t us_taskquit;
uintptr_t us_textstart;
uintptr_t us_textend;
uintptr_t us_datasource;
uintptr_t us_datastart;
uintptr_t us_dataend;
uintptr_t us_bssstart;
uintptr_t us_bssend;
uintptr_t us_heapend;
};
#define USERSPACE (( struct UserSpaceS *)(MEMORY_END_ADDRESS + G_SERVICE_TABLE_LENGTH))
#ifndef SERVICE_TABLE_ADDRESS
#define SERVICE_TABLE_ADDRESS (0x80100000)
#endif
#define USER_MEMORY_START_ADDRESS (USERSPACE->us_bssend)
#define USER_MEMORY_END_ADDRESS (void*)((0x80000000 + 6 * 1024 * 1024) )
#else
#define MEMORY_START_ADDRESS (void*)&__stack_end__
#define MEMORY_END_ADDRESS (void*)(0x80000000 + 6 * 1024 * 1024)
#endif
void InitBoardHardware(void);
#endif

View File

@ -0,0 +1,17 @@
export CFLAGS := -mcmodel=medany -march=rv64imac -mabi=lp64 -fno-common -ffunction-sections -fdata-sections -fstrict-volatile-bitfields -O0 -Wa,-g -ggdb -fgnu89-inline -Werror
export AFLAGS := -c -mcmodel=medany -march=rv64imac -mabi=lp64 -Wa,-g -ggdb
export LFLAGS := -mcmodel=medany -march=rv64imac -mabi=lp64 -nostartfiles -Wl,--gc-sections,-Map=XiUOS_kd233.map,-cref,-u,_start -T $(BSP_ROOT)/link.lds
export APPLFLAGS := -mcmodel=medany -march=rv64imac -mabi=lp64 -nostartfiles -Wl,--gc-sections,-Map=XiUOS_app.map,-cref,-u, -T $(BSP_ROOT)/link_userspace.lds
export CXXFLAGS := -mcmodel=medany -march=rv64imac -mabi=lp64 -fno-common -ffunction-sections -fdata-sections -fstrict-volatile-bitfields -O0 -Wa,-g -ggdb -Werror
export CROSS_COMPILE ?=/opt/gnu-mcu-eclipse/riscv-none-gcc/8.2.0-2.1-20190425-1021/bin/riscv-none-embed-
export DEFINES := -DHAVE_CCONFIG_H -DHAVE_SIGINFO
export ARCH = risc-v
export MCU = k210

Binary file not shown.

After

Width:  |  Height:  |  Size: 63 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 83 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 158 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 42 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 56 KiB

View File

@ -0,0 +1,253 @@
/* Copyright 2018 Canaan Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* @file atomic.h
* @brief add from Canaan K210 SDK
* https://canaan-creative.com/developer
* @version 1.0
* @author AIIT XUOS Lab
* @date 2021-04-25
*/
#ifndef _BSP_ATOMIC_H
#define _BSP_ATOMIC_H
#ifdef __cplusplus
extern "C" {
#endif
#define SPINLOCK_INIT \
{ \
0 \
}
#define CORELOCK_INIT \
{ \
.lock = SPINLOCK_INIT, \
.count = 0, \
.core = -1 \
}
/* Defination of memory barrier macro */
#define mb() \
{ \
asm volatile("fence" :: \
: "memory"); \
}
#define atomic_set(ptr, val) (*(volatile typeof(*(ptr))*)(ptr) = val)
#define atomic_read(ptr) (*(volatile typeof(*(ptr))*)(ptr))
#ifndef __riscv_atomic
#error "atomic extension is required."
#endif
#define atomic_add(ptr, inc) __sync_fetch_and_add(ptr, inc)
#define atomic_or(ptr, inc) __sync_fetch_and_or(ptr, inc)
#define atomic_swap(ptr, swp) __sync_lock_test_and_set(ptr, swp)
#define atomic_cas(ptr, cmp, swp) __sync_val_compare_and_swap(ptr, cmp, swp)
typedef struct _spinlock
{
int lock;
} spinlock_t;
typedef struct _semaphore
{
spinlock_t lock;
int count;
int waiting;
} semaphore_t;
typedef struct _corelock
{
spinlock_t lock;
int count;
int core;
} corelock_t;
static inline int spinlock_trylock(spinlock_t *lock)
{
int res = atomic_swap(&lock->lock, -1);
/* Use memory barrier to keep coherency */
mb();
return res;
}
static inline void spinlock_lock(spinlock_t *lock)
{
while (spinlock_trylock(lock));
}
static inline void spinlock_unlock(spinlock_t *lock)
{
/* Use memory barrier to keep coherency */
mb();
atomic_set(&lock->lock, 0);
asm volatile ("nop");
}
static inline void semaphore_signal(semaphore_t *semaphore, int i)
{
spinlock_lock(&(semaphore->lock));
semaphore->count += i;
spinlock_unlock(&(semaphore->lock));
}
static inline void semaphore_wait(semaphore_t *semaphore, int i)
{
atomic_add(&(semaphore->waiting), 1);
while (1)
{
spinlock_lock(&(semaphore->lock));
if (semaphore->count >= i)
{
semaphore->count -= i;
atomic_add(&(semaphore->waiting), -1);
spinlock_unlock(&(semaphore->lock));
break;
}
spinlock_unlock(&(semaphore->lock));
}
}
static inline int semaphore_count(semaphore_t *semaphore)
{
int res = 0;
spinlock_lock(&(semaphore->lock));
res = semaphore->count;
spinlock_unlock(&(semaphore->lock));
return res;
}
static inline int semaphore_waiting(semaphore_t *semaphore)
{
return atomic_read(&(semaphore->waiting));
}
static inline int corelock_trylock(corelock_t *lock)
{
int res = 0;
unsigned long core;
asm volatile("csrr %0, mhartid;"
: "=r"(core));
if(spinlock_trylock(&lock->lock))
{
return -1;
}
if (lock->count == 0)
{
/* First time get lock */
lock->count++;
lock->core = core;
res = 0;
}
else if (lock->core == core)
{
/* Same core get lock */
lock->count++;
res = 0;
}
else
{
/* Different core get lock */
res = -1;
}
spinlock_unlock(&lock->lock);
return res;
}
static inline void corelock_lock(corelock_t *lock)
{
unsigned long core;
asm volatile("csrr %0, mhartid;"
: "=r"(core));
spinlock_lock(&lock->lock);
if (lock->count == 0)
{
/* First time get lock */
lock->count++;
lock->core = core;
}
else if (lock->core == core)
{
/* Same core get lock */
lock->count++;
}
else
{
/* Different core get lock */
spinlock_unlock(&lock->lock);
do
{
while (atomic_read(&lock->count))
;
} while (corelock_trylock(lock));
return;
}
spinlock_unlock(&lock->lock);
}
static inline void corelock_unlock(corelock_t *lock)
{
unsigned long core;
asm volatile("csrr %0, mhartid;"
: "=r"(core));
spinlock_lock(&lock->lock);
if (lock->core == core)
{
/* Same core release lock */
lock->count--;
if (lock->count <= 0)
{
lock->core = -1;
lock->count = 0;
}
}
else
{
/* Different core release lock */
spinlock_unlock(&lock->lock);
register unsigned long a7 asm("a7") = 93;
register unsigned long a0 asm("a0") = 0;
register unsigned long a1 asm("a1") = 0;
register unsigned long a2 asm("a2") = 0;
asm volatile("scall"
: "+r"(a0)
: "r"(a1), "r"(a2), "r"(a7));
}
spinlock_unlock(&lock->lock);
}
#ifdef __cplusplus
}
#endif
#endif /* _BSP_ATOMIC_H */

View File

@ -0,0 +1,31 @@
/* Copyright 2018 Canaan Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* @file bsp.h
* @brief add from Canaan K210 SDK
* https://canaan-creative.com/developer
* @version 1.0
* @author AIIT XUOS Lab
* @date 2021-04-25
*/
#ifndef _KENDRYTE_BSP_H
#define _KENDRYTE_BSP_H
#include "atomic.h"
#include "entry.h"
#include "sleep.h"
#include "encoding.h"
#endif

View File

@ -0,0 +1,150 @@
/* Copyright 2018 Canaan Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* @file dump.h
* @brief add from Canaan K210 SDK
* https://canaan-creative.com/developer
* @version 1.0
* @author AIIT XUOS Lab
* @date 2021-04-25
*/
#ifndef _BSP_DUMP_H
#define _BSP_DUMP_H
#include <stdlib.h>
#include <string.h>
#include "syslog.h"
#include "hardware_uarths.h"
#ifdef __cplusplus
extern "C" {
#endif
#define DUMP_PRINTF printk
static inline void
dump_core(const char *reason, uintptr_t cause, uintptr_t epc, uintptr_t regs[32], uintptr_t fregs[32])
{
static const char *const reg_usage[][2] =
{
{"zero ", "Hard-wired zero"},
{"ra ", "Return address"},
{"sp ", "Stack pointer"},
{"gp ", "Global pointer"},
{"tp ", "Task pointer"},
{"t0 ", "Temporaries Caller"},
{"t1 ", "Temporaries Caller"},
{"t2 ", "Temporaries Caller"},
{"s0/fp", "Saved register/frame pointer"},
{"s1 ", "Saved register"},
{"a0 ", "Function arguments/return values"},
{"a1 ", "Function arguments/return values"},
{"a2 ", "Function arguments values"},
{"a3 ", "Function arguments values"},
{"a4 ", "Function arguments values"},
{"a5 ", "Function arguments values"},
{"a6 ", "Function arguments values"},
{"a7 ", "Function arguments values"},
{"s2 ", "Saved registers"},
{"s3 ", "Saved registers"},
{"s4 ", "Saved registers"},
{"s5 ", "Saved registers"},
{"s6 ", "Saved registers"},
{"s7 ", "Saved registers"},
{"s8 ", "Saved registers"},
{"s9 ", "Saved registers"},
{"s10 ", "Saved registers"},
{"s11 ", "Saved registers"},
{"t3 ", "Temporaries Caller"},
{"t4 ", "Temporaries Caller"},
{"t5 ", "Temporaries Caller"},
{"t6 ", "Temporaries Caller"},
};
static const char *const regf_usage[][2] =
{
{"ft0 ", "FP temporaries"},
{"ft1 ", "FP temporaries"},
{"ft2 ", "FP temporaries"},
{"ft3 ", "FP temporaries"},
{"ft4 ", "FP temporaries"},
{"ft5 ", "FP temporaries"},
{"ft6 ", "FP temporaries"},
{"ft7 ", "FP temporaries"},
{"fs0 ", "FP saved registers"},
{"fs1 ", "FP saved registers"},
{"fa0 ", "FP arguments/return values"},
{"fa1 ", "FP arguments/return values"},
{"fa2 ", "FP arguments values"},
{"fa3 ", "FP arguments values"},
{"fa4 ", "FP arguments values"},
{"fa5 ", "FP arguments values"},
{"fa6 ", "FP arguments values"},
{"fa7 ", "FP arguments values"},
{"fs2 ", "FP Saved registers"},
{"fs3 ", "FP Saved registers"},
{"fs4 ", "FP Saved registers"},
{"fs5 ", "FP Saved registers"},
{"fs6 ", "FP Saved registers"},
{"fs7 ", "FP Saved registers"},
{"fs8 ", "FP Saved registers"},
{"fs9 ", "FP Saved registers"},
{"fs10", "FP Saved registers"},
{"fs11", "FP Saved registers"},
{"ft8 ", "FP Temporaries Caller"},
{"ft9 ", "FP Temporaries Caller"},
{"ft10", "FP Temporaries Caller"},
{"ft11", "FP Temporaries Caller"},
};
if (CONFIG_LOG_LEVEL >= LOG_ERROR)
{
const char unknown_reason[] = "unknown";
if (!reason)
reason = unknown_reason;
DUMP_PRINTF("core dump: %s\r\n", reason);
DUMP_PRINTF("Cause 0x%016lx, EPC 0x%016lx\r\n", cause, epc);
int i = 0;
for (i = 0; i < 32 / 2; i++)
{
DUMP_PRINTF(
"reg[%02d](%s) = 0x%016lx, reg[%02d](%s) = 0x%016lx\r\n",
i * 2, reg_usage[i * 2][0], regs[i * 2],
i * 2 + 1, reg_usage[i * 2 + 1][0], regs[i * 2 + 1]);
}
for (i = 0; i < 32 / 2; i++)
{
DUMP_PRINTF(
"freg[%02d](%s) = 0x%016lx(%f), freg[%02d](%s) = 0x%016lx(%f)\r\n",
i * 2, regf_usage[i * 2][0], fregs[i * 2], (float)fregs[i * 2],
i * 2 + 1, regf_usage[i * 2 + 1][0], fregs[i * 2 + 1], (float)fregs[i * 2 + 1]);
}
}
}
#undef DUMP_PRINTF
#ifdef __cplusplus
}
#endif
#endif /* _BSP_DUMP_H */

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,90 @@
/* Copyright 2018 Canaan Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* @file entry.h
* @brief add from Canaan K210 SDK
* https://canaan-creative.com/developer
* @version 1.0
* @author AIIT XUOS Lab
* @date 2021-04-25
*/
#ifndef _BSP_ENTRY_H
#define _BSP_ENTRY_H
#include <stdlib.h>
#include <string.h>
#ifdef __cplusplus
extern "C" {
#endif
typedef int (*core_function)(void *ctx);
typedef struct _core_instance_t
{
core_function callback;
void *ctx;
} core_instance_t;
int register_core1(core_function func, void *ctx);
static inline void init_lma(void)
{
extern unsigned int _data_lma;
extern unsigned int _data;
extern unsigned int _edata;
unsigned int *src, *dst;
src = &_data_lma;
dst = &_data;
while (dst < &_edata)
*dst++ = *src++;
}
static inline void InitBss(void)
{
extern unsigned int _bss;
extern unsigned int _ebss;
unsigned int *dst;
dst = &_bss;
while (dst < &_ebss)
*dst++ = 0;
}
static inline void init_tls(void)
{
register void *task_pointer asm("tp");
extern char _tls_data;
extern __thread char _tdata_begin, _tdata_end, _tbss_end;
size_t tdata_size = &_tdata_end - &_tdata_begin;
memcpy(task_pointer, &_tls_data, tdata_size);
size_t tbss_size = &_tbss_end - &_tdata_end;
memset(task_pointer + tdata_size, 0, tbss_size);
}
#ifdef __cplusplus
}
#endif
#endif /* _BSP_ENTRY_H */

View File

@ -0,0 +1,56 @@
/* Copyright 2018 Canaan Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* @file interrupt.h
* @brief add from Canaan K210 SDK
* https://canaan-creative.com/developer
* @version 1.0
* @author AIIT XUOS Lab
* @date 2021-04-25
*/
#ifndef _BSP_INTERRUPT_H
#define _BSP_INTERRUPT_H
#ifdef __cplusplus
extern "C" {
#endif
/* clang-format off */
/* Machine interrupt mask for 64 bit system, 0x8000 0000 0000 0000 */
#define CAUSE_MACHINE_IRQ_MASK (0x1ULL << 63)
/* Machine interrupt reason mask for 64 bit system, 0x7FFF FFFF FFFF FFFF */
#define CAUSE_MACHINE_IRQ_REASON_MASK (CAUSE_MACHINE_IRQ_MASK - 1)
/* Hypervisor interrupt mask for 64 bit system, 0x8000 0000 0000 0000 */
#define CAUSE_HYPERVISOR_IRQ_MASK (0x1ULL << 63)
/* Hypervisor interrupt reason mask for 64 bit system, 0x7FFF FFFF FFFF FFFF */
#define CAUSE_HYPERVISOR_IRQ_REASON_MASK (CAUSE_HYPERVISOR_IRQ_MASK - 1)
/* Supervisor interrupt mask for 64 bit system, 0x8000 0000 0000 0000 */
#define CAUSE_SUPERVISOR_IRQ_MASK (0x1ULL << 63)
/* Supervisor interrupt reason mask for 64 bit system, 0x7FFF FFFF FFFF FFFF */
#define CAUSE_SUPERVISOR_IRQ_REASON_MASK (CAUSE_SUPERVISOR_IRQ_MASK - 1)
/* clang-format on */
#ifdef __cplusplus
}
#endif
#endif /* _BSP_INTERRUPT_H */

View File

@ -0,0 +1,108 @@
/* Copyright 2018 Canaan Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* @file platform.h
* @brief add from Canaan K210 SDK
* https://canaan-creative.com/developer
* @version 1.0
* @author AIIT XUOS Lab
* @date 2021-04-25
*/
#ifndef _BSP_PLATFORM_H
#define _BSP_PLATFORM_H
#ifdef __cplusplus
extern "C" {
#endif
/* clang-format off */
/* Register base address */
/* Under Coreplex */
#define CLINT_BASE_ADDR (0x02000000U)
#define PLIC_BASE_ADDR (0x0C000000U)
/* Under TileLink */
#define UARTHS_BASE_ADDR (0x10010000U)
#define GPIOHS_BASE_ADDR (0x38001000U)
/* Under AXI 64 bit */
#define RAM_BASE_ADDR (0x80000000U)
#define RAM_SIZE (6 * 1024 * 1024U)
#define IO_BASE_ADDR (0x40000000U)
#define IO_SIZE (6 * 1024 * 1024U)
#define AI_RAM_BASE_ADDR (0x80600000U)
#define AI_RAM_SIZE (2 * 1024 * 1024U)
#define AI_IO_BASE_ADDR (0x40600000U)
#define AI_IO_SIZE (2 * 1024 * 1024U)
#define AI_BASE_ADDR (0x40800000U)
#define AI_SIZE (12 * 1024 * 1024U)
#define FFT_BASE_ADDR (0x42000000U)
#define FFT_SIZE (4 * 1024 * 1024U)
#define ROM_BASE_ADDR (0x88000000U)
#define ROM_SIZE (128 * 1024U)
/* Under AHB 32 bit */
#define DMAC_BASE_ADDR (0x50000000U)
/* Under APB1 32 bit */
#define GPIO_BASE_ADDR (0x50200000U)
#define UART1_BASE_ADDR (0x50210000U)
#define UART2_BASE_ADDR (0x50220000U)
#define UART3_BASE_ADDR (0x50230000U)
#define SPI_SLAVE_BASE_ADDR (0x50240000U)
#define I2S0_BASE_ADDR (0x50250000U)
#define I2S1_BASE_ADDR (0x50260000U)
#define I2S2_BASE_ADDR (0x50270000U)
#define I2C0_BASE_ADDR (0x50280000U)
#define I2C1_BASE_ADDR (0x50290000U)
#define I2C2_BASE_ADDR (0x502A0000U)
#define FPIOA_BASE_ADDR (0x502B0000U)
#define SHA256_BASE_ADDR (0x502C0000U)
#define TIMER0_BASE_ADDR (0x502D0000U)
#define TIMER1_BASE_ADDR (0x502E0000U)
#define TIMER2_BASE_ADDR (0x502F0000U)
/* Under APB2 32 bit */
#define WDT0_BASE_ADDR (0x50400000U)
#define WDT1_BASE_ADDR (0x50410000U)
#define OTP_BASE_ADDR (0x50420000U)
#define DVP_BASE_ADDR (0x50430000U)
#define SYSCTL_BASE_ADDR (0x50440000U)
#define AES_BASE_ADDR (0x50450000U)
#define RTC_BASE_ADDR (0x50460000U)
/* Under APB3 32 bit */
#define SPI0_BASE_ADDR (0x52000000U)
#define SPI1_BASE_ADDR (0x53000000U)
#define SPI3_BASE_ADDR (0x54000000U)
/* clang-format on */
#ifdef __cplusplus
}
#endif
#endif /* _BSP_PLATFORM_H */

View File

@ -0,0 +1,218 @@
/**
* File: printf.h
*
* Copyright (c) 2004,2012 Kustaa Nyholm / SpareTimeLabs
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of Kustaa Nyholm or SpareTimeLabs nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* This library is really just two files: 'tinyprintf.h' and 'tinyprintf.c'.
*
* They provide a simple and small (+400 loc) printf functionality to be used
* in embedded systems.
*
* I've found them so useful in debugging that I do not bother with a debugger
* at all.
*
* They are distributed in source form, so to use them, just compile them into
* your project.
*
* Two printf variants are provided: printf and the 'sprintf' family of
* functions ('snprintf', 'sprintf', 'vsnprintf', 'vsprintf').
*
* The formats supported by this implementation are: 'c' 'd' 'i' 'o' 'p' 'u'
* 's' 'x' 'X'.
*
* Zero padding, field width, and precision are also supported.
*
* If the library is compiled with 'PRINTF_SUPPORT_LONG' defined, then the
* long specifier is also supported. Note that this will pull in some long
* math routines (pun intended!) and thus make your executable noticeably
* longer. Likewise with 'PRINTF_LONG_LONG_SUPPORT' for the long long
* specifier, and with 'PRINTF_SIZE_T_SUPPORT' for the size_t specifier.
*
* The memory footprint of course depends on the target CPU, compiler and
* compiler options, but a rough guesstimate (based on a H8S target) is about
* 1.4 kB for code and some twenty 'int's and 'char's, say 60 bytes of stack
* space. Not too bad. Your mileage may vary. By hacking the source code you
* can get rid of some hundred bytes, I'm sure, but personally I feel the
* balance of functionality and flexibility versus code size is close to
* optimal for many embedded systems.
*
* To use the printf, you need to supply your own character output function,
* something like :
*
* void putc ( void* p, char c) { while (!SERIAL_PORT_EMPTY) ;
* SERIAL_PORT_TX_REGISTER = c; }
*
* Before you can call printf, you need to initialize it to use your character
* output function with something like:
*
* init_printf(NULL,putc);
*
* Notice the 'NULL' in 'init_printf' and the parameter 'void* p' in 'putc',
* the NULL (or any pointer) you pass into the 'init_printf' will eventually
* be passed to your 'putc' routine. This allows you to pass some storage
* space (or anything really) to the character output function, if necessary.
* This is not often needed but it was implemented like that because it made
* implementing the sprintf function so neat (look at the source code).
*
* The code is re-entrant, except for the 'init_printf' function, so it is
* safe to call it from interrupts too, although this may result in mixed
* output. If you rely on re-entrancy, take care that your 'putc' function is
* re-entrant!
*
* The printf and sprintf functions are actually macros that translate to
* 'tfp_printf' and 'tfp_sprintf' when 'TINYPRINTF_OVERRIDE_LIBC' is set
* (default). Setting it to 0 makes it possible to use them along with
* 'stdio.h' printf's in a single source file. When 'TINYPRINTF_OVERRIDE_LIBC'
* is set, please note that printf/sprintf are not function-like macros, so if
* you have variables or struct members with these names, things will explode
* in your face. Without variadic macros this is the best we can do to wrap
* these function. If it is a problem, just give up the macros and use the
* functions directly, or rename them.
*
* It is also possible to avoid defining tfp_printf and/or tfp_sprintf by
* clearing 'TINYPRINTF_DEFINE_TFP_PRINTF' and/or
* 'TINYPRINTF_DEFINE_TFP_SPRINTF' to 0. This allows for example to export
* only tfp_format, which is at the core of all the other functions.
*
* For further details see source code.
*
* regs Kusti, 23.10.2004
*/
/**
* @file printf.h
* @brief add from Canaan K210 SDK
* https://canaan-creative.com/developer
* @version 1.0
* @author AIIT XUOS Lab
* @date 2021-04-25
*/
#ifndef _BSP_PRINTF_H
#define _BSP_PRINTF_H
#include <stdarg.h>
#include <stddef.h>
/* Global configuration */
/* Set this to 0 if you do not want to provide tfp_printf */
#ifndef TINYPRINTF_DEFINE_TFP_PRINTF
#define TINYPRINTF_DEFINE_TFP_PRINTF 1
#endif
/**
* Set this to 0 if you do not want to provide
* tfp_sprintf/snprintf/vsprintf/vsnprintf
*/
#ifndef TINYPRINTF_DEFINE_TFP_SPRINTF
#define TINYPRINTF_DEFINE_TFP_SPRINTF 1
#endif
/**
* Set this to 0 if you do not want tfp_printf and
* tfp_{vsn,sn,vs,s}printf to be also available as
* printf/{vsn,sn,vs,s}printf
*/
#ifndef TINYPRINTF_OVERRIDE_LIBC
#define TINYPRINTF_OVERRIDE_LIBC 0
#endif
/* Optional external types dependencies */
/* Declarations */
#if defined(__GNUC__)
#define _TFP_SPECIFY_PRINTF_FMT(fmt_idx, arg1_idx) \
__attribute__((format(printf, fmt_idx, arg1_idx)))
#else
#define _TFP_SPECIFY_PRINTF_FMT(fmt_idx, arg1_idx)
#endif
#ifdef __cplusplus
extern "C" {
#endif
typedef void (*putcf)(void*, char);
/**
* 'tfp_format' really is the central function for all tinyprintf. For
* each output character after formatting, the 'putf' callback is
* called with 2 args:
* - an arbitrary void* 'putp' param defined by the user and
* passed unmodified from 'tfp_format',
* - the character.
* The 'tfp_printf' and 'tfp_sprintf' functions simply define their own
* callback and pass to it the right 'putp' it is expecting.
*/
void tfp_format(void *putp, putcf putf, const char *fmt, va_list va);
#if TINYPRINTF_DEFINE_TFP_SPRINTF
int tfp_vsnprintf(char *str, size_t size, const char *fmt, va_list ap);
int tfp_snprintf(char *str, size_t size, const char *fmt, ...)
_TFP_SPECIFY_PRINTF_FMT(3, 4);
int tfp_vsprintf(char *str, const char *fmt, va_list ap);
int tfp_sprintf(char *str, const char *fmt, ...) _TFP_SPECIFY_PRINTF_FMT(2, 3);
#if TINYPRINTF_OVERRIDE_LIBC
#define vsnprintf tfp_vsnprintf
#define snprintf tfp_snprintf
#define vsprintf tfp_vsprintf
#define sprintf tfp_sprintf
#endif
#endif
#if TINYPRINTF_DEFINE_TFP_PRINTF
void init_printf(void *putp, putcf putf);
void tfp_printf(char *fmt, ...) _TFP_SPECIFY_PRINTF_FMT(1, 2);
#if TINYPRINTF_OVERRIDE_LIBC
#define printf tfp_printf
#ifdef __cplusplus
#include <forward_list>
namespace std
{
template <typename... Args>
auto tfp_printf(Args&&... args) -> decltype(::tfp_printf(std::forward<Args>(args)...))
{
return ::tfp_printf(std::forward<Args>(args)...);
}
}
#endif
#endif
#endif
int printk(const char *format, ...) _TFP_SPECIFY_PRINTF_FMT(1, 2);
#ifdef __cplusplus
}
#endif
#endif /* _BSP_PRINTF_H */

View File

@ -0,0 +1,45 @@
/* Copyright 2018 Canaan Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* @file sleep.h
* @brief add from Canaan K210 SDK
* https://canaan-creative.com/developer
* @version 1.0
* @author AIIT XUOS Lab
* @date 2021-04-25
*/
#ifndef _BSP_SLEEP_H
#define _BSP_SLEEP_H
#include "encoding.h"
#include "clint.h"
#include "syscalls.h"
#ifdef __cplusplus
extern "C" {
#endif
int usleep(uint64_t usec);
int msleep(uint64_t msec);
unsigned int sleep(unsigned int seconds);
#ifdef __cplusplus
}
#endif
#endif /* _BSP_SLEEP_H */

View File

@ -0,0 +1,54 @@
/* Copyright 2018 Canaan Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* @file syscalls.h
* @brief add from Canaan K210 SDK
* https://canaan-creative.com/developer
* @version 1.0
* @author AIIT XUOS Lab
* @date 2021-04-25
*/
#ifndef _BSP_SYSCALLS_H
#define _BSP_SYSCALLS_H
#include <machine/syscall.h>
#include <stddef.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#ifdef __cplusplus
extern "C" {
#endif
void __attribute__((noreturn)) sys_exit(int code);
void setStats(int enable);
#undef putchar
int putchar(int ch);
void printstr(const char *s);
void printhex(uint64_t x);
#ifdef __cplusplus
}
#endif
#endif /* _BSP_SYSCALLS_H */

View File

@ -0,0 +1,151 @@
/* Copyright 2018 Canaan Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* @file syslog.h
* @brief add from Canaan K210 SDK
* https://canaan-creative.com/developer
* @version 1.0
* @author AIIT XUOS Lab
* @date 2021-04-25
*/
#ifndef _SYSLOG_H
#define _SYSLOG_H
#include <stdint.h>
#include <stdio.h>
#include "printf.h"
#include "encoding.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Logging library
*
* Log library has two ways of managing log verbosity: compile time, set via
* menuconfig
*
* At compile time, filtering is done using CONFIG_LOG_DEFAULT_LEVEL macro, set via
* menuconfig. All logging statments for levels higher than CONFIG_LOG_DEFAULT_LEVEL
* will be removed by the preprocessor.
*
*
* How to use this library:
*
* In each C file which uses logging functionality, define TAG variable like this:
*
* static const char *TAG = "MODULE_NAME";
*
* then use one of logging macros to produce output, e.g:
*
* LOGW(TAG, "Interrupt error %d", error);
*
* Several macros are available for different verbosity levels:
*
* LOGE - error
* LOGW - warning
* LOGI - info
* LOGD - debug
* LOGV - verbose
*
* To override default verbosity level at file or component scope, define LOG_LEVEL macro.
* At file scope, define it before including esp_log.h, e.g.:
*
* #define LOG_LEVEL LOG_VERBOSE
* #include "dxx_log.h"
*
* At component scope, define it in component makefile:
*
* CFLAGS += -D LOG_LEVEL=LOG_DEBUG
*
*
*/
/* clang-format off */
typedef enum _kendryte_log_level
{
LOG_NONE, /*!< No log output */
LOG_ERROR, /*!< Critical errors, software module can not recover on its own */
LOG_WARN, /*!< Error conditions from which recovery measures have been taken */
LOG_INFO, /*!< Information messages which describe normal flow of events */
LOG_DEBUG, /*!< Extra information which is not necessary for normal use (values, pointers, sizes, etc). */
LOG_VERBOSE /*!< Bigger chunks of debugging information, or frequent messages which can potentially flood the output. */
} kendryte_log_level_t ;
/* clang-format on */
/* clang-format off */
#if CONFIG_LOG_COLORS
#define LOG_COLOR_BLACK "30"
#define LOG_COLOR_RED "31"
#define LOG_COLOR_GREEN "32"
#define LOG_COLOR_BROWN "33"
#define LOG_COLOR_BLUE "34"
#define LOG_COLOR_PURPLE "35"
#define LOG_COLOR_CYAN "36"
#define LOG_COLOR(COLOR) "\033[0;" COLOR "m"
#define LOG_BOLD(COLOR) "\033[1;" COLOR "m"
#define LOG_RESET_COLOR "\033[0m"
#define LOG_COLOR_E LOG_COLOR(LOG_COLOR_RED)
#define LOG_COLOR_W LOG_COLOR(LOG_COLOR_BROWN)
#define LOG_COLOR_I LOG_COLOR(LOG_COLOR_GREEN)
#define LOG_COLOR_D
#define LOG_COLOR_V
#else /* CONFIG_LOG_COLORS */
#define LOG_COLOR_E
#define LOG_COLOR_W
#define LOG_COLOR_I
#define LOG_COLOR_D
#define LOG_COLOR_V
#define LOG_RESET_COLOR
#endif /* CONFIG_LOG_COLORS */
/* clang-format on */
#define LOG_FORMAT(letter, format) LOG_COLOR_ ## letter #letter " (%lu) %s: " format LOG_RESET_COLOR "\n"
#ifdef LOG_LEVEL
#undef CONFIG_LOG_LEVEL
#define CONFIG_LOG_LEVEL LOG_LEVEL
#endif
#ifdef LOG_KERNEL
#define LOG_PRINTF printk
#else
#define LOG_PRINTF printf
#endif
#ifdef CONFIG_LOG_ENABLE
#define LOGE(tag, format, ...) do {if (CONFIG_LOG_LEVEL >= LOG_ERROR) LOG_PRINTF(LOG_FORMAT(E, format), read_cycle(), tag, ##__VA_ARGS__); } while (0)
#define LOGW(tag, format, ...) do {if (CONFIG_LOG_LEVEL >= LOG_WARN) LOG_PRINTF(LOG_FORMAT(W, format), read_cycle(), tag, ##__VA_ARGS__); } while (0)
#define LOGI(tag, format, ...) do {if (CONFIG_LOG_LEVEL >= LOG_INFO) LOG_PRINTF(LOG_FORMAT(I, format), read_cycle(), tag, ##__VA_ARGS__); } while (0)
#define LOGD(tag, format, ...) do {if (CONFIG_LOG_LEVEL >= LOG_DEBUG) LOG_PRINTF(LOG_FORMAT(D, format), read_cycle(), tag, ##__VA_ARGS__); } while (0)
#define LOGV(tag, format, ...) do {if (CONFIG_LOG_LEVEL >= LOG_VERBOSE) LOG_PRINTF(LOG_FORMAT(V, format), read_cycle(), tag, ##__VA_ARGS__); } while (0)
#else
#define LOGE(tag, format, ...)
#define LOGW(tag, format, ...)
#define LOGI(tag, format, ...)
#define LOGD(tag, format, ...)
#define LOGV(tag, format, ...)
#endif /* LOG_ENABLE */
#ifdef __cplusplus
}
#endif
#endif /* _SYSLOG_H */

View File

@ -0,0 +1,207 @@
/* Copyright 2018 Canaan Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* @file util.h
* @brief add from Canaan K210 SDK
* https://canaan-creative.com/developer
* @version 1.0
* @author AIIT XUOS Lab
* @date 2021-04-25
*/
#ifndef _BSP_UTIL_H
#define _BSP_UTIL_H
#include <stdint.h>
#if defined(__riscv)
#include "encoding.h"
#endif
#ifdef __cplusplus
extern "C" {
#endif
#if defined(__GNUC__)
#pragma GCC diagnostic ignored "-Wunused-parameter"
#pragma GCC diagnostic ignored "-Wunused-function"
#endif
/**
* --------------------------------------------------------------------------
* Macros
* Set HOST_DEBUG to 1 if you are going to compile this for a host
* machine (ie Athena/Linux) for debug purposes and set HOST_DEBUG
* to 0 if you are compiling with the smips-gcc toolchain.
*/
#ifndef HOST_DEBUG
#define HOST_DEBUG 0
#endif
/**
* Set PREALLOCATE to 1 if you want to preallocate the benchmark
* function before starting stats. If you have instruction/data
* caches and you don't want to count the overhead of misses, then
* you will need to use preallocation.
*/
#ifndef PREALLOCATE
#define PREALLOCATE 0
#endif
#define static_assert(cond) \
{ \
switch (0) \
{ \
case 0: \
case !!(long)(cond):; \
} \
}
#define stringify_1(s) #s
#define stringify(s) stringify_1(s)
#define stats(code, iter) \
do \
{ \
unsigned long _c = -read_cycle(), _i = -READ_CSR(minstret); \
code; \
_c += read_cycle(), _i += READ_CSR(minstret); \
if (cid == 0) \
printf("\r\n%s: %ld cycles, %ld.%ld cycles/iter, %ld.%ld CPI\r\n", \
stringify(code), _c, _c / iter, 10 * _c / iter % 10, _c / _i, 10 * _c / _i % 10); \
} while (0)
/**
* Set SET_STATS to 1 if you want to carve out the piece that actually
* does the computation.
*/
#if HOST_DEBUG
#include <stdio.h>
static void setStats(int enable) {}
#else
extern void setStats(int enable);
#endif
static void printArray(const char name[], int n, const int arr[])
{
#if HOST_DEBUG
int i;
printf(" %10s :", name);
for (i = 0; i < n; i++)
printf(" %3d ", arr[i]);
printf("\r\n");
#endif
}
static void printDoubleArray(const char name[], int n, const double arr[])
{
#if HOST_DEBUG
int i;
printf(" %10s :", name);
for (i = 0; i < n; i++)
printf(" %g ", arr[i]);
printf("\r\n");
#endif
}
static int verify(int n, const volatile int *test, const int *verify)
{
int i;
/* Unrolled for faster verification */
for (i = 0; i < n / 2 * 2; i += 2)
{
int t0 = test[i], t1 = test[i + 1];
int v0 = verify[i], v1 = verify[i + 1];
if (t0 != v0)
return i + 1;
if (t1 != v1)
return i + 2;
}
if (n % 2 != 0 && test[n - 1] != verify[n - 1])
return n;
return 0;
}
static int verifyDouble(int n, const volatile double *test, const double *verify)
{
int i;
/* Unrolled for faster verification */
for (i = 0; i < n / 2 * 2; i += 2)
{
double t0 = test[i], t1 = test[i + 1];
double v0 = verify[i], v1 = verify[i + 1];
int eq1 = t0 == v0, eq2 = t1 == v1;
if (!(eq1 & eq2))
return i + 1 + eq1;
}
if (n % 2 != 0 && test[n - 1] != verify[n - 1])
return n;
return 0;
}
static void __attribute__((noinline)) barrier(int ncores)
{
static volatile int sense = 0;
static volatile int count = 0;
static __thread int threadsense;
__sync_synchronize();
threadsense = !threadsense;
if (__sync_fetch_and_add(&count, 1) == ncores - 1)
{
count = 0;
sense = threadsense;
}
else
{
while (sense != threadsense)
;
}
__sync_synchronize();
}
static uint64_t lfsr(uint64_t x)
{
uint64_t bit = (x ^ (x >> 1)) & 1;
return (x >> 1) | (bit << 62);
}
#if defined(__GNUC__)
#pragma GCC diagnostic warning "-Wunused-parameter"
#pragma GCC diagnostic warning "-Wunused-function"
#endif
#ifdef __cplusplus
}
#endif
#endif /* _BSP_UTIL_H */

View File

@ -0,0 +1,118 @@
/*
* Copyright (c) 2020 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
__STACKSIZE__ = 4096;
OUTPUT_ARCH( "riscv" )
MEMORY
{
sram (wxa!ri): ORIGIN = 0x80000000, LENGTH = ( 6 * 1024 * 1024 )
}
ENTRY(_begin)
SECTIONS
{
.start :
{
*(.start);
} > sram
. = ALIGN(8);
.text :
{
PROVIDE( _text = ABSOLUTE(.) );
*(.text .text.*) /* Normal code */
*(.rodata .rodata*) /* read-only data (constants) */
/* section information for shell */
. = ALIGN(8);
_shell_command_start = .;
KEEP (*(shellCommand))
_shell_command_end = .;
. = ALIGN(8);
PROVIDE(__ctors_start__ = .);
KEEP (*(SORT(.init_array.*)))
KEEP (*(.init_array))
PROVIDE(__ctors_end__ = .);
. = ALIGN(4);
__isrtbl_idx_start = .;
KEEP(*(.isrtbl.idx))
__isrtbl_start = .;
KEEP(*(.isrtbl))
__isrtbl_end = .;
. = ALIGN(8);
PROVIDE(g_service_table_start = ABSOLUTE(.));
KEEP(*(.g_service_table))
PROVIDE(g_service_table_end = ABSOLUTE(.));
PROVIDE( _etext = ABSOLUTE(.) );
} > sram
. = ALIGN(8);
.data :
{
PROVIDE( _sdata = ABSOLUTE(.) );
/* Writable data segment */
*(.data .data.*)
. = ALIGN(8);
PROVIDE( __global_pointer$ = ABSOLUTE(.) + 0x800 );
/* Writable small data segment (.sdata segment) */
*(.sdata .sdata.*)
PROVIDE( _edata = ABSOLUTE(.) );
} > sram
.bss :
{
__bss_start = ABSOLUTE(.);
/* Writable uninitialized small data segment (.sbss segment)*/
*(.sbss .sbss.*)
*(.scommon)
/* Uninitialized writeable data section (.bss segment)*/
*(.bss .bss.*)
*(COMMON)
. = ALIGN(8);
__bss_end = ABSOLUTE(.);
} > sram
.stack :
{
. = ALIGN(64);
PROVIDE(__stack_start__ = ABSOLUTE(.));
/* cpu0 stack top site */
. = . + __STACKSIZE__;
__stack_tp0 = . ;
/* cpu1 stack top site */
. = . + __STACKSIZE__;
__stack_tp1 = . ;
PROVIDE( __stack_end__ = ABSOLUTE(.) );
} > sram
_end = ABSOLUTE(.);
/* Stabs debugging sections. */
}

View File

@ -0,0 +1,70 @@
/*
* Copyright (c) 2020 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
OUTPUT_ARCH("riscv")
MEMORY
{
usram (rw) : ORIGIN = 0x80101000, LENGTH = ( 5 * 1024 * 1024 - 4 * 1024 ) /* 5M -4k usram */
}
SECTIONS
{
.userspace :
{
. = ALIGN(8);
KEEP(*(.userspace))
} > usram
.text :
{
_ustext = ABSOLUTE(.);
*(.text .text.*)
*(.rodata .rodata*)
*(.glue_7)
*(.glue_7t)
PROVIDE(_uetext = ABSOLUTE(.));
} > usram
.init_section : {
_sinit = ABSOLUTE(.);
KEEP(*(.init_array .init_array.*))
_einit = ABSOLUTE(.);
} > usram
__uexidx_start = ABSOLUTE(.);
.ARM.exidx :
{
PROVIDE(__uexidx_start = ABSOLUTE(.));
*(.ARM.exidx* .gnu.linkonce.armexidx.*)
PROVIDE(__uexidx_end = ABSOLUTE(.));
} > usram
_ueronly = ABSOLUTE(.);
.data : AT(_ueronly)
{
_usdata = ABSOLUTE(.);
*(.data .data.*)
. = ALIGN(8);
_uedata = ABSOLUTE(.);
} > usram
.bss : {
. = ALIGN(8);
_usbss = ABSOLUTE(.);
*(.bss .bss.*)
*(.sbss .sbss.*)
. = ALIGN(8);
_uebss = ABSOLUTE(.);
} > usram
}

View File

@ -0,0 +1,45 @@
menuconfig BSP_USING_DMA
bool "Using DMA device"
default y
if BSP_USING_DMA
source "$BSP_DIR/third_party_driver/dma/Kconfig"
endif
menuconfig BSP_USING_GPIO
bool "Using GPIO device"
default y
select RESOURCES_PIN
if BSP_USING_GPIO
source "$BSP_DIR/third_party_driver/gpio/Kconfig"
endif
menuconfig BSP_USING_PLIC
bool "Using PLIC device"
default y
if BSP_USING_PLIC
source "$BSP_DIR/third_party_driver/plic/Kconfig"
endif
menuconfig BSP_USING_SYSCLOCK
bool "Using SYSCLOCK device"
default y
if BSP_USING_SYSCLOCK
source "$BSP_DIR/third_party_driver/sys_clock/Kconfig"
endif
menuconfig BSP_USING_HWTIMER
bool "Using HWTIMER device"
default n
select RESOURCES_HWTIMER
if BSP_USING_HWTIMER
source "$BSP_DIR/third_party_driver/timer/Kconfig"
endif
menuconfig BSP_USING_UART
bool "Using UART device"
default y
select RESOURCES_SERIAL
if BSP_USING_UART
source "$BSP_DIR/third_party_driver/uart/Kconfig"
endif

View File

@ -0,0 +1,35 @@
SRC_FILES := sleep.c
ifeq ($(CONFIG_BSP_USING_DMA),y)
SRC_DIR += dma
endif
ifeq ($(CONFIG_BSP_USING_GPIO),y)
SRC_DIR += gpio
endif
ifeq ($(CONFIG_BSP_USING_PLIC),y)
SRC_DIR += plic
endif
ifeq ($(CONFIG_BSP_USING_SECURITY),y)
SRC_DIR += security
endif
ifeq ($(CONFIG_BSP_USING_SYSCLOCK),y)
SRC_DIR += sys_clock
endif
ifeq ($(CONFIG_BSP_USING_HWTIMER),y)
SRC_DIR += timer
endif
ifeq ($(CONFIG_BSP_USING_UART),y)
SRC_DIR += uart
endif
include $(KERNEL_ROOT)/compiler.mk

View File

@ -0,0 +1 @@

View File

@ -0,0 +1,6 @@
SRC_FILES := dmac.c
include $(KERNEL_ROOT)/compiler.mk

View File

@ -0,0 +1,802 @@
/* Copyright 2018 Canaan Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License"},
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* @file dmac.c
* @brief add from Canaan K210 SDK
* https://canaan-creative.com/developer
* @version 1.0
* @author AIIT XUOS Lab
* @date 2021-04-25
*/
#include <stdint.h>
#include <stddef.h>
#include <stdio.h>
#include "dmac.h"
#include "sysctl.h"
#include "fpioa.h"
#include "utils.h"
#include "plic.h"
#include "stdlib.h"
volatile dmac_t *const dmac = (dmac_t *)DMAC_BASE_ADDR;
typedef struct _dmac_context
{
dmac_channel_number_t dmac_channel;
plic_irq_callback_t callback;
void *ctx;
} dmac_context_t;
dmac_context_t dmac_context[6];
static int is_memory(uintptr_t address)
{
enum {
mem_len = 6 * 1024 * 1024,
mem_no_cache_len = 8 * 1024 * 1024,
};
return ((address >= 0x80000000) && (address < 0x80000000 + mem_len)) || ((address >= 0x40000000) && (address < 0x40000000 + mem_no_cache_len)) || (address == 0x50450040);
}
uint64_t dmac_read_id(void)
{
return dmac->id;
}
uint64_t dmac_read_version(void)
{
return dmac->compver;
}
uint64_t dmac_read_channel_id(dmac_channel_number_t channel_num)
{
return dmac->channel[channel_num].axi_id;
}
static void dmac_enable(void)
{
dmac_cfg_u_t dmac_cfg;
dmac_cfg.data = readq(&dmac->cfg);
dmac_cfg.cfg.dmac_en = 1;
dmac_cfg.cfg.int_en = 1;
writeq(dmac_cfg.data, &dmac->cfg);
}
void dmac_disable(void)
{
dmac_cfg_u_t dmac_cfg;
dmac_cfg.data = readq(&dmac->cfg);
dmac_cfg.cfg.dmac_en = 0;
dmac_cfg.cfg.int_en = 0;
writeq(dmac_cfg.data, &dmac->cfg);
}
void src_transaction_complete_int_enable(dmac_channel_number_t channel_num)
{
dmac_ch_intstatus_enable_u_t ch_intstat;
ch_intstat.data = readq(&dmac->channel[channel_num].intstatus_en);
ch_intstat.ch_intstatus_enable.enable_src_transcomp_intstat = 1;
writeq(ch_intstat.data, &dmac->channel[channel_num].intstatus_en);
}
void dmac_channel_enable(dmac_channel_number_t channel_num)
{
dmac_chen_u_t chen;
chen.data = readq(&dmac->chen);
switch (channel_num) {
case DMAC_CHANNEL0:
chen.dmac_chen.ch1_en = 1;
chen.dmac_chen.ch1_en_we = 1;
break;
case DMAC_CHANNEL1:
chen.dmac_chen.ch2_en = 1;
chen.dmac_chen.ch2_en_we = 1;
break;
case DMAC_CHANNEL2:
chen.dmac_chen.ch3_en = 1;
chen.dmac_chen.ch3_en_we = 1;
break;
case DMAC_CHANNEL3:
chen.dmac_chen.ch4_en = 1;
chen.dmac_chen.ch4_en_we = 1;
break;
case DMAC_CHANNEL4:
chen.dmac_chen.ch5_en = 1;
chen.dmac_chen.ch5_en_we = 1;
break;
case DMAC_CHANNEL5:
chen.dmac_chen.ch6_en = 1;
chen.dmac_chen.ch6_en_we = 1;
break;
default:
break;
}
writeq(chen.data, &dmac->chen);
}
void dmac_channel_disable(dmac_channel_number_t channel_num)
{
dmac_chen_u_t chen;
chen.data = readq(&dmac->chen);
switch (channel_num)
{
case DMAC_CHANNEL0:
chen.dmac_chen.ch1_en = 0;
chen.dmac_chen.ch1_en_we = 1;
break;
case DMAC_CHANNEL1:
chen.dmac_chen.ch2_en = 0;
chen.dmac_chen.ch2_en_we = 1;
break;
case DMAC_CHANNEL2:
chen.dmac_chen.ch3_en = 0;
chen.dmac_chen.ch3_en_we = 1;
break;
case DMAC_CHANNEL3:
chen.dmac_chen.ch4_en = 0;
chen.dmac_chen.ch4_en_we = 1;
break;
case DMAC_CHANNEL4:
chen.dmac_chen.ch5_en = 0;
chen.dmac_chen.ch5_en_we = 1;
break;
case DMAC_CHANNEL5:
chen.dmac_chen.ch6_en = 0;
chen.dmac_chen.ch6_en_we = 1;
break;
default:
break;
}
writeq(chen.data, &dmac->chen);
}
int32_t dmac_check_channel_busy(dmac_channel_number_t channel_num)
{
int32_t ret = 0;
dmac_chen_u_t chen_u;
chen_u.data = readq(&dmac->chen);
switch (channel_num) {
case DMAC_CHANNEL0:
if (chen_u.dmac_chen.ch1_en == 1)
ret = 1;
break;
case DMAC_CHANNEL1:
if (chen_u.dmac_chen.ch2_en == 1)
ret = 1;
break;
case DMAC_CHANNEL2:
if (chen_u.dmac_chen.ch3_en == 1)
ret = 1;
break;
case DMAC_CHANNEL3:
if (chen_u.dmac_chen.ch4_en == 1)
ret = 1;
break;
case DMAC_CHANNEL4:
if (chen_u.dmac_chen.ch5_en == 1)
ret = 1;
break;
case DMAC_CHANNEL5:
if (chen_u.dmac_chen.ch6_en == 1)
ret = 1;
break;
default:
break;
}
writeq(chen_u.data, &dmac->chen);
return ret;
}
int32_t dmac_set_list_master_select(dmac_channel_number_t channel_num,
dmac_src_dst_select_t sd_sel, dmac_master_number_t mst_num)
{
int32_t ret = 0;
uint64_t tmp = 0;
dmac_ch_ctl_u_t ctl;
ctl.data = readq(&dmac->channel[channel_num].ctl);
ret = dmac_check_channel_busy(channel_num);
if (ret == 0) {
if (sd_sel == DMAC_SRC || sd_sel == DMAC_SRC_DST)
ctl.ch_ctl.sms = mst_num;
if (sd_sel == DMAC_DST || sd_sel == DMAC_SRC_DST)
ctl.ch_ctl.dms = mst_num;
tmp |= *(uint64_t *)&dmac->channel[channel_num].ctl;
writeq(ctl.data, &dmac->channel[channel_num].ctl);
}
return ret;
}
void dmac_enable_common_interrupt_status(void)
{
dmac_commonreg_intstatus_enable_u_t intstatus;
intstatus.data = readq(&dmac->com_intstatus_en);
intstatus.intstatus_enable.enable_slvif_dec_err_intstat = 1;
intstatus.intstatus_enable.enable_slvif_wr2ro_err_intstat = 1;
intstatus.intstatus_enable.enable_slvif_rd2wo_err_intstat = 1;
intstatus.intstatus_enable.enable_slvif_wronhold_err_intstat = 1;
intstatus.intstatus_enable.enable_slvif_undefinedreg_dec_err_intstat = 1;
writeq(intstatus.data, &dmac->com_intstatus_en);
}
void dmac_enable_common_interrupt_signal(void)
{
dmac_commonreg_intsignal_enable_u_t intsignal;
intsignal.data = readq(&dmac->com_intsignal_en);
intsignal.intsignal_enable.enable_slvif_dec_err_intsignal = 1;
intsignal.intsignal_enable.enable_slvif_wr2ro_err_intsignal = 1;
intsignal.intsignal_enable.enable_slvif_rd2wo_err_intsignal = 1;
intsignal.intsignal_enable.enable_slvif_wronhold_err_intsignal = 1;
intsignal.intsignal_enable.enable_slvif_undefinedreg_dec_err_intsignal = 1;
writeq(intsignal.data, &dmac->com_intsignal_en);
}
static void dmac_enable_channel_interrupt(dmac_channel_number_t channel_num)
{
writeq(0xffffffff, &dmac->channel[channel_num].intclear);
writeq(0x2, &dmac->channel[channel_num].intstatus_en);
}
void dmac_disable_channel_interrupt(dmac_channel_number_t channel_num)
{
writeq(0, &dmac->channel[channel_num].intstatus_en);
}
static void dmac_chanel_interrupt_clear(dmac_channel_number_t channel_num)
{
writeq(0xffffffff, &dmac->channel[channel_num].intclear);
}
int dmac_set_channel_config(dmac_channel_number_t channel_num,
dmac_channel_config_t *cfg_param)
{
dmac_ch_ctl_u_t ctl;
dmac_ch_cfg_u_t cfg;
dmac_ch_llp_u_t ch_llp;
if (cfg_param->ctl_sms > DMAC_MASTER2)
return -1;
if (cfg_param->ctl_dms > DMAC_MASTER2)
return -1;
if (cfg_param->ctl_src_msize > DMAC_MSIZE_256)
return -1;
if (cfg_param->ctl_drc_msize > DMAC_MSIZE_256)
return -1;
/**
* cfg register must configure before ts_block and
* sar dar register
*/
cfg.data = readq(&dmac->channel[channel_num].cfg);
cfg.ch_cfg.hs_sel_src = cfg_param->cfg_hs_sel_src;
cfg.ch_cfg.hs_sel_dst = cfg_param->cfg_hs_sel_dst;
cfg.ch_cfg.src_hwhs_pol = cfg_param->cfg_src_hs_pol;
cfg.ch_cfg.dst_hwhs_pol = cfg_param->cfg_dst_hs_pol;
cfg.ch_cfg.src_per = cfg_param->cfg_src_per;
cfg.ch_cfg.dst_per = cfg_param->cfg_dst_per;
cfg.ch_cfg.ch_prior = cfg_param->cfg_ch_prior;
cfg.ch_cfg.tt_fc = cfg_param->ctl_tt_fc;
cfg.ch_cfg.src_multblk_type = cfg_param->cfg_src_multblk_type;
cfg.ch_cfg.dst_multblk_type = cfg_param->cfg_dst_multblk_type;
writeq(cfg.data, &dmac->channel[channel_num].cfg);
ctl.data = readq(&dmac->channel[channel_num].ctl);
ctl.ch_ctl.sms = cfg_param->ctl_sms;
ctl.ch_ctl.dms = cfg_param->ctl_dms;
/* master select */
ctl.ch_ctl.sinc = cfg_param->ctl_sinc;
ctl.ch_ctl.dinc = cfg_param->ctl_dinc;
/* address incrememt */
ctl.ch_ctl.src_tr_width = cfg_param->ctl_src_tr_width;
ctl.ch_ctl.dst_tr_width = cfg_param->ctl_dst_tr_width;
/* transfer width */
ctl.ch_ctl.src_msize = cfg_param->ctl_src_msize;
ctl.ch_ctl.dst_msize = cfg_param->ctl_drc_msize;
/* Burst transaction length */
ctl.ch_ctl.ioc_blktfr = cfg_param->ctl_ioc_blktfr;
/* interrupt on completion of block transfer */
/* 0x1 enable BLOCK_TFR_DONE_IntStat field */
writeq(cfg_param->ctl_block_ts, &dmac->channel[channel_num].block_ts);
/* the number of (blcok_ts +1) data of width SRC_TR_WIDTF to be */
/* transferred in a dma block transfer */
dmac->channel[channel_num].sar = cfg_param->sar;
dmac->channel[channel_num].dar = cfg_param->dar;
ch_llp.data = readq(&dmac->channel[channel_num].llp);
ch_llp.llp.loc = cfg_param->llp_loc;
ch_llp.llp.lms = cfg_param->llp_lms;
writeq(ch_llp.data, &dmac->channel[channel_num].llp);
writeq(ctl.data, &dmac->channel[channel_num].ctl);
readq(&dmac->channel[channel_num].swhssrc);
return 0;
}
int dmac_set_channel_param(dmac_channel_number_t channel_num,
const void *src, void *dest, dmac_address_increment_t src_inc, dmac_address_increment_t dest_inc,
dmac_burst_trans_length_t dmac_burst_size,
dmac_transfer_width_t dmac_trans_width,
uint32_t blockSize)
{
dmac_ch_ctl_u_t ctl;
dmac_ch_cfg_u_t cfg_u;
int mem_type_src = is_memory((uintptr_t)src), mem_type_dest = is_memory((uintptr_t)dest);
dmac_transfer_flow_t flow_control;
if (mem_type_src == 0 && mem_type_dest == 0)
{
flow_control = DMAC_PRF2PRF_DMA;
}else if (mem_type_src == 1 && mem_type_dest == 0)
flow_control = DMAC_MEM2PRF_DMA;
else if (mem_type_src == 0 && mem_type_dest == 1)
flow_control = DMAC_PRF2MEM_DMA;
else
flow_control = DMAC_MEM2MEM_DMA;
/**
* cfg register must configure before ts_block and
* sar dar register
*/
cfg_u.data = readq(&dmac->channel[channel_num].cfg);
cfg_u.ch_cfg.tt_fc = flow_control;
cfg_u.ch_cfg.hs_sel_src = mem_type_src ? DMAC_HS_SOFTWARE : DMAC_HS_HARDWARE;
cfg_u.ch_cfg.hs_sel_dst = mem_type_dest ? DMAC_HS_SOFTWARE : DMAC_HS_HARDWARE;
cfg_u.ch_cfg.src_per = channel_num;
cfg_u.ch_cfg.dst_per = channel_num;
cfg_u.ch_cfg.src_multblk_type = 0;
cfg_u.ch_cfg.dst_multblk_type = 0;
writeq(cfg_u.data, &dmac->channel[channel_num].cfg);
dmac->channel[channel_num].sar = (uint64_t)src;
dmac->channel[channel_num].dar = (uint64_t)dest;
ctl.data = readq(&dmac->channel[channel_num].ctl);
ctl.ch_ctl.sms = DMAC_MASTER1;
ctl.ch_ctl.dms = DMAC_MASTER2;
/* master select */
ctl.ch_ctl.sinc = src_inc;
ctl.ch_ctl.dinc = dest_inc;
/* address incrememt */
ctl.ch_ctl.src_tr_width = dmac_trans_width;
ctl.ch_ctl.dst_tr_width = dmac_trans_width;
/* transfer width */
ctl.ch_ctl.src_msize = dmac_burst_size;
ctl.ch_ctl.dst_msize = dmac_burst_size;
writeq(ctl.data, &dmac->channel[channel_num].ctl);
writeq(blockSize - 1, &dmac->channel[channel_num].block_ts);
/*the number of (blcok_ts +1) data of width SRC_TR_WIDTF to be */
/* transferred in a dma block transfer */
return 0;
}
int dmac_get_channel_config(dmac_channel_number_t channel_num,
dmac_channel_config_t *cfg_param)
{
dmac_ch_ctl_u_t ctl;
dmac_ch_cfg_u_t cfg;
dmac_ch_llp_u_t ch_llp;
if (cfg_param == 0)
return -1;
if (channel_num < DMAC_CHANNEL0 ||
channel_num > DMAC_CHANNEL3)
return -1;
ctl.data = readq(&dmac->channel[channel_num].ctl);
cfg_param->ctl_sms = ctl.ch_ctl.sms;
cfg_param->ctl_dms = ctl.ch_ctl.dms;
cfg_param->ctl_sinc = ctl.ch_ctl.sinc;
cfg_param->ctl_dinc = ctl.ch_ctl.dinc;
cfg_param->ctl_src_tr_width = ctl.ch_ctl.src_tr_width;
cfg_param->ctl_dst_tr_width = ctl.ch_ctl.dst_tr_width;
cfg_param->ctl_src_msize = ctl.ch_ctl.src_msize;
cfg_param->ctl_drc_msize = ctl.ch_ctl.dst_msize;
cfg_param->ctl_ioc_blktfr = ctl.ch_ctl.ioc_blktfr;
cfg.data = readq(&dmac->channel[channel_num].cfg);
cfg_param->cfg_hs_sel_src = cfg.ch_cfg.hs_sel_src;
cfg_param->cfg_hs_sel_dst = cfg.ch_cfg.hs_sel_dst;
cfg_param->cfg_src_hs_pol = cfg.ch_cfg.src_hwhs_pol;
cfg_param->cfg_dst_hs_pol = cfg.ch_cfg.dst_hwhs_pol;
cfg_param->cfg_src_per = cfg.ch_cfg.src_per;
cfg_param->cfg_dst_per = cfg.ch_cfg.dst_per;
cfg_param->cfg_ch_prior = cfg.ch_cfg.ch_prior;
cfg_param->cfg_src_multblk_type = cfg.ch_cfg.src_multblk_type;
cfg_param->cfg_dst_multblk_type = cfg.ch_cfg.dst_multblk_type;
cfg_param->sar = dmac->channel[channel_num].sar;
cfg_param->dar = dmac->channel[channel_num].dar;
ch_llp.data = readq(&dmac->channel[channel_num].llp);
cfg_param->llp_loc = ch_llp.llp.loc;
cfg_param->llp_lms = ch_llp.llp.lms;
cfg_param->ctl_block_ts = readq(&dmac->channel[channel_num].block_ts);
return 0;
}
void dmac_set_address(dmac_channel_number_t channel_num, uint64_t src_addr,
uint64_t dst_addr)
{
writeq(src_addr, &dmac->channel[channel_num].sar);
writeq(dst_addr, &dmac->channel[channel_num].dar);
}
void dmac_set_block_ts(dmac_channel_number_t channel_num,
uint32_t BlockSize)
{
uint32_t block_ts;
block_ts = BlockSize & 0x3fffff;
writeq(block_ts, &dmac->channel[channel_num].block_ts);
}
void dmac_source_control(dmac_channel_number_t channel_num,
dmac_master_number_t master_select,
dmac_address_increment_t address_mode,
dmac_transfer_width_t tr_width,
dmac_burst_trans_length_t burst_length)
{
dmac_ch_ctl_u_t ctl_u;
ctl_u.data = readq(&dmac->channel[channel_num].ctl);
ctl_u.ch_ctl.sms = master_select;
ctl_u.ch_ctl.sinc = address_mode;
ctl_u.ch_ctl.src_tr_width = tr_width;
ctl_u.ch_ctl.src_msize = burst_length;
writeq(ctl_u.data, &dmac->channel[channel_num].ctl);
}
void dmac_master_control(dmac_channel_number_t channel_num,
dmac_master_number_t master_select,
dmac_address_increment_t address_mode,
dmac_transfer_width_t tr_width,
dmac_burst_trans_length_t burst_length)
{
dmac_ch_ctl_u_t ctl_u;
ctl_u.data = readq(&dmac->channel[channel_num].ctl);
ctl_u.ch_ctl.dms = master_select;
ctl_u.ch_ctl.dinc = address_mode;
ctl_u.ch_ctl.dst_tr_width = tr_width;
ctl_u.ch_ctl.dst_msize = burst_length;
writeq(ctl_u.data, &dmac->channel[channel_num].ctl);
}
void dmac_set_source_transfer_control(dmac_channel_number_t channel_num,
dmac_multiblk_transfer_type_t transfer_type,
dmac_sw_hw_hs_select_t handshak_select)
{
dmac_ch_cfg_u_t cfg_u;
cfg_u.data = readq(&dmac->channel[channel_num].cfg);
cfg_u.ch_cfg.src_multblk_type = transfer_type;
cfg_u.ch_cfg.hs_sel_src = handshak_select;
writeq(cfg_u.data, &dmac->channel[channel_num].cfg);
}
void dmac_set_destination_transfer_control(dmac_channel_number_t channel_num,
dmac_multiblk_transfer_type_t transfer_type,
dmac_sw_hw_hs_select_t handshak_select)
{
dmac_ch_cfg_u_t cfg_u;
cfg_u.data = readq(&dmac->channel[channel_num].cfg);
cfg_u.ch_cfg.dst_multblk_type = transfer_type;
cfg_u.ch_cfg.hs_sel_dst = handshak_select;
writeq(cfg_u.data, &dmac->channel[channel_num].cfg);
}
void dmac_set_flow_control(dmac_channel_number_t channel_num,
dmac_transfer_flow_t flow_control)
{
dmac_ch_cfg_u_t cfg_u;
cfg_u.data = readq(&dmac->channel[channel_num].cfg);
cfg_u.ch_cfg.tt_fc = flow_control;
writeq(cfg_u.data, &dmac->channel[channel_num].cfg);
}
void dmac_set_linked_list_addr_point(dmac_channel_number_t channel_num,
uint64_t *addr)
{
dmac_ch_llp_u_t llp_u;
llp_u.data = readq(&dmac->channel[channel_num].llp);
/* Cast pointer to uint64_t */
llp_u.llp.loc = (uint64_t)addr;
writeq(llp_u.data, &dmac->channel[channel_num].llp);
}
void DmacInit(void)
{
uint64_t tmp;
dmac_commonreg_intclear_u_t intclear;
dmac_cfg_u_t dmac_cfg;
dmac_reset_u_t dmac_reset;
sysctl_clock_enable(SYSCTL_CLOCK_DMA);
dmac_reset.data = readq(&dmac->reset);
dmac_reset.reset.rst = 1;
writeq(dmac_reset.data, &dmac->reset);
while (dmac_reset.reset.rst)
dmac_reset.data = readq(&dmac->reset);
/*reset dmac */
intclear.data = readq(&dmac->com_intclear);
intclear.com_intclear.cear_slvif_dec_err_intstat = 1;
intclear.com_intclear.clear_slvif_wr2ro_err_intstat = 1;
intclear.com_intclear.clear_slvif_rd2wo_err_intstat = 1;
intclear.com_intclear.clear_slvif_wronhold_err_intstat = 1;
intclear.com_intclear.clear_slvif_undefinedreg_dec_err_intstat = 1;
writeq(intclear.data, &dmac->com_intclear);
/* clear common register interrupt */
dmac_cfg.data = readq(&dmac->cfg);
dmac_cfg.cfg.dmac_en = 0;
dmac_cfg.cfg.int_en = 0;
writeq(dmac_cfg.data, &dmac->cfg);
/* disable dmac and disable interrupt */
while (readq(&dmac->cfg))
;
tmp = readq(&dmac->chen);
tmp &= ~0xf;
writeq(tmp, &dmac->chen);
/* disable all channel before configure */
dmac_enable();
}
static void list_add(struct list_head_t *new, struct list_head_t *prev,
struct list_head_t *next)
{
next->prev = new;
new->next = next;
new->prev = prev;
prev->next = new;
}
void list_add_tail(struct list_head_t *new, struct list_head_t *head)
{
list_add(new, head->prev, head);
}
void INIT_LIST_HEAD(struct list_head_t *list)
{
list->next = list;
list->prev = list;
}
void dmac_link_list_item(dmac_channel_number_t channel_num,
uint8_t LLI_row_num, int8_t LLI_last_row,
dmac_lli_item_t *lli_item,
dmac_channel_config_t *cfg_param)
{
dmac_ch_ctl_u_t ctl;
dmac_ch_llp_u_t llp_u;
lli_item[LLI_row_num].sar = cfg_param->sar;
lli_item[LLI_row_num].dar = cfg_param->dar;
ctl.data = readq(&dmac->channel[channel_num].ctl);
ctl.ch_ctl.sms = cfg_param->ctl_sms;
ctl.ch_ctl.dms = cfg_param->ctl_dms;
ctl.ch_ctl.sinc = cfg_param->ctl_sinc;
ctl.ch_ctl.dinc = cfg_param->ctl_dinc;
ctl.ch_ctl.src_tr_width = cfg_param->ctl_src_tr_width;
ctl.ch_ctl.dst_tr_width = cfg_param->ctl_dst_tr_width;
ctl.ch_ctl.src_msize = cfg_param->ctl_src_msize;
ctl.ch_ctl.dst_msize = cfg_param->ctl_drc_msize;
ctl.ch_ctl.src_stat_en = cfg_param->ctl_src_stat_en;
ctl.ch_ctl.dst_stat_en = cfg_param->ctl_dst_stat_en;
if (LLI_last_row != LAST_ROW) {
ctl.ch_ctl.shadowreg_or_lli_valid = 1;
ctl.ch_ctl.shadowreg_or_lli_last = 0;
} else {
ctl.ch_ctl.shadowreg_or_lli_valid = 1;
ctl.ch_ctl.shadowreg_or_lli_last = 1;
}
lli_item[LLI_row_num].ctl = ctl.data;
lli_item[LLI_row_num].ch_block_ts = cfg_param->ctl_block_ts;
lli_item[LLI_row_num].sstat = 0;
lli_item[LLI_row_num].dstat = 0;
llp_u.data = readq(&dmac->channel[channel_num].llp);
if (LLI_last_row != LAST_ROW)
llp_u.llp.loc = ((uint64_t)&lli_item[LLI_row_num + 1]) >> 6;
else
llp_u.llp.loc = 0;
lli_item[LLI_row_num].llp = llp_u.data;
}
void dmac_update_shandow_register(dmac_channel_number_t channel_num,
int8_t last_block, dmac_channel_config_t *cfg_param)
{
dmac_ch_ctl_u_t ctl_u;
do {
ctl_u.data = readq(&dmac->channel[channel_num].ctl);
} while (ctl_u.ch_ctl.shadowreg_or_lli_valid);
writeq(cfg_param->sar, &dmac->channel[channel_num].sar);
writeq(cfg_param->dar, &dmac->channel[channel_num].dar);
writeq(cfg_param->ctl_block_ts, &dmac->channel[channel_num].block_ts);
ctl_u.ch_ctl.sms = cfg_param->ctl_sms;
ctl_u.ch_ctl.dms = cfg_param->ctl_dms;
ctl_u.ch_ctl.sinc = cfg_param->ctl_sinc;
ctl_u.ch_ctl.dinc = cfg_param->ctl_dinc;
ctl_u.ch_ctl.src_tr_width = cfg_param->ctl_src_tr_width;
ctl_u.ch_ctl.dst_tr_width = cfg_param->ctl_dst_tr_width;
ctl_u.ch_ctl.src_msize = cfg_param->ctl_src_msize;
ctl_u.ch_ctl.dst_msize = cfg_param->ctl_drc_msize;
ctl_u.ch_ctl.src_stat_en = cfg_param->ctl_src_stat_en;
ctl_u.ch_ctl.dst_stat_en = cfg_param->ctl_dst_stat_en;
if (last_block != LAST_ROW)
{
ctl_u.ch_ctl.shadowreg_or_lli_valid = 1;
ctl_u.ch_ctl.shadowreg_or_lli_last = 0;
} else {
ctl_u.ch_ctl.shadowreg_or_lli_valid = 1;
ctl_u.ch_ctl.shadowreg_or_lli_last = 1;
}
writeq(ctl_u.data, &dmac->channel[channel_num].ctl);
writeq(0, &dmac->channel[channel_num].blk_tfr);
}
void dmac_set_shadow_invalid_flag(dmac_channel_number_t channel_num)
{
dmac_ch_ctl_u_t ctl_u;
ctl_u.data = readq(&dmac->channel[channel_num].ctl);
ctl_u.ch_ctl.shadowreg_or_lli_valid = 1;
ctl_u.ch_ctl.shadowreg_or_lli_last = 0;
writeq(ctl_u.data, &dmac->channel[channel_num].ctl);
}
void dmac_set_single_mode(dmac_channel_number_t channel_num,
const void *src, void *dest, dmac_address_increment_t src_inc,
dmac_address_increment_t dest_inc,
dmac_burst_trans_length_t dmac_burst_size,
dmac_transfer_width_t dmac_trans_width,
size_t BlockSize) {
dmac_chanel_interrupt_clear(channel_num);
dmac_channel_disable(channel_num);
dmac_wait_idle(channel_num);
dmac_set_channel_param(channel_num, src, dest, src_inc, dest_inc,
dmac_burst_size, dmac_trans_width, BlockSize);
dmac_enable();
dmac_channel_enable(channel_num);
}
int dmac_is_done(dmac_channel_number_t channel_num)
{
if(readq(&dmac->channel[channel_num].intstatus) & 0x2)
return 1;
else
return 0;
}
void dmac_wait_done(dmac_channel_number_t channel_num)
{
dmac_wait_idle(channel_num);
}
int dmac_is_idle(dmac_channel_number_t channel_num)
{
dmac_chen_u_t chen;
chen.data = readq(&dmac->chen);
if((chen.data >> channel_num) & 0x1UL)
return 0;
else
return 1;
}
void dmac_wait_idle(dmac_channel_number_t channel_num)
{
while(!dmac_is_idle(channel_num));
dmac_chanel_interrupt_clear(channel_num); /* clear interrupt */
}
void dmac_set_src_dest_length(dmac_channel_number_t channel_num, const void *src, void *dest, size_t len)
{
if(src != NULL)
dmac->channel[channel_num].sar = (uint64_t)src;
if(dest != NULL)
dmac->channel[channel_num].dar = (uint64_t)dest;
if(len > 0)
dmac_set_block_ts(channel_num, len - 1);
dmac_channel_enable(channel_num);
}
static int dmac_irq_callback(void *ctx)
{
dmac_context_t *v_dmac_context = (dmac_context_t *)(ctx);
dmac_channel_number_t v_dmac_channel = v_dmac_context->dmac_channel;
dmac_chanel_interrupt_clear(v_dmac_channel);
if(v_dmac_context->callback != NULL)
v_dmac_context->callback(v_dmac_context->ctx);
return 0;
}
void dmac_irq_register(dmac_channel_number_t channel_num , plic_irq_callback_t dmac_callback, void *ctx, uint32_t priority)
{
dmac_context[channel_num].dmac_channel = channel_num;
dmac_context[channel_num].callback = dmac_callback;
dmac_context[channel_num].ctx = ctx;
dmac_enable_channel_interrupt(channel_num);
plic_set_priority(IRQN_DMA0_INTERRUPT + channel_num, priority);
plic_irq_enable(IRQN_DMA0_INTERRUPT + channel_num);
plic_irq_register(IRQN_DMA0_INTERRUPT + channel_num, dmac_irq_callback, &dmac_context[channel_num]);
}
void __attribute__((weak, alias("dmac_irq_register"))) dmac_set_irq(dmac_channel_number_t channel_num , plic_irq_callback_t dmac_callback, void *ctx, uint32_t priority);
void dmac_irq_unregister(dmac_channel_number_t channel_num)
{
dmac_context[channel_num].callback = NULL;
dmac_context[channel_num].ctx = NULL;
dmac_disable_channel_interrupt(channel_num);
plic_irq_unregister(IRQN_DMA0_INTERRUPT + channel_num);
}
void __attribute__((weak, alias("dmac_irq_unregister"))) dmac_free_irq(dmac_channel_number_t channel_num);

View File

@ -0,0 +1,11 @@
config PIN_BUS_NAME
string "pin bus name"
default "pin"
config PIN_DRIVER_NAME
string "pin driver name"
default "pin_drv"
config PIN_DEVICE_NAME
string "pin device name"
default "pin_dev"

View File

@ -0,0 +1,8 @@
SRC_FILES := connect_gpio.c drv_io_config.c fpioa.c gpio.c gpiohs.c utils.c
include $(KERNEL_ROOT)/compiler.mk

View File

@ -0,0 +1,331 @@
/*
* Copyright (c) 2006-2018, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2019-03-19 ZYH first version
*/
/**
* @file connect_gpio.c
* @brief support gpio function using bus driver framework
* @version 1.0
* @author AIIT XUOS Lab
* @date 2021-04-25
*/
/*************************************************
File name: connect_gpio.c
Description: support gpio configure and register to bus framework
Others: take RT-Thread v4.0.2/bsp/k210/driver/drv_gpio.c for references
https://github.com/RT-Thread/rt-thread/tree/v4.0.2
History:
1. Date: 2021-04-25
Author: AIIT XUOS Lab
Modification: add bus driver framework support for gpio
*************************************************/
#include <xiuos.h>
#include <device.h>
#include <fpioa.h>
#include <gpiohs.h>
#include "drv_io_config.h"
#include <plic.h>
#include <utils.h>
#include "connect_gpio.h"
#define FUNC_GPIOHS(n) (FUNC_GPIOHS0 + n)
static int pin_alloc_table[FPIOA_NUM_IO];
static uint32_t free_pin = 0;
static int AllocPinChannel(x_base pin_index)
{
if (free_pin == 31) {
SYS_ERR("no free gpiohs channel to alloc");
return -1;
}
if (pin_alloc_table[pin_index] != -1) {
SYS_WARN("already alloc gpiohs channel for pin %d", pin_index);
return pin_alloc_table[pin_index];
}
pin_alloc_table[pin_index] = free_pin;
free_pin++;
FpioaSetFunction(pin_index, FUNC_GPIOHS(pin_alloc_table[pin_index]));
return pin_alloc_table[pin_index];
}
static int GetPinChannel(x_base pin_index)
{
return pin_alloc_table[pin_index];
}
static uint32 GpioConfigMode(int mode, uint8_t pin_channel)
{
switch (mode)
{
case GPIO_CFG_OUTPUT:
gpiohs_set_drive_mode(pin_channel, GPIO_DM_OUTPUT);
break;
case GPIO_CFG_INPUT:
gpiohs_set_drive_mode(pin_channel, GPIO_DM_INPUT);
break;
case GPIO_CFG_INPUT_PULLUP:
gpiohs_set_drive_mode(pin_channel, GPIO_DM_INPUT_PULL_UP);
break;
case GPIO_CFG_INPUT_PULLDOWN:
gpiohs_set_drive_mode(pin_channel, GPIO_DM_INPUT_PULL_DOWN);
break;
case GPIO_CFG_OUTPUT_OD:
break;
default:
break;
}
return EOK;
}
static struct
{
void (*hdr)(void *args);
void *args;
GpioPinEdgeT edge;
} IrqTable[32];
static void pin_irq(int vector, void *param)
{
int pin_channel = vector - IRQN_GPIOHS0_INTERRUPT;
if (IrqTable[pin_channel].edge & GPIO_PE_FALLING) {
set_gpio_bit(gpiohs->fall_ie.u32, pin_channel, 0);
set_gpio_bit(gpiohs->fall_ip.u32, pin_channel, 1);
set_gpio_bit(gpiohs->fall_ie.u32, pin_channel, 1);
}
if (IrqTable[pin_channel].edge & GPIO_PE_RISING) {
set_gpio_bit(gpiohs->rise_ie.u32, pin_channel, 0);
set_gpio_bit(gpiohs->rise_ip.u32, pin_channel, 1);
set_gpio_bit(gpiohs->rise_ie.u32, pin_channel, 1);
}
if (IrqTable[pin_channel].edge & GPIO_PE_LOW) {
set_gpio_bit(gpiohs->low_ie.u32, pin_channel, 0);
set_gpio_bit(gpiohs->low_ip.u32, pin_channel, 1);
set_gpio_bit(gpiohs->low_ie.u32, pin_channel, 1);
}
if (IrqTable[pin_channel].edge & GPIO_PE_HIGH) {
set_gpio_bit(gpiohs->high_ie.u32, pin_channel, 0);
set_gpio_bit(gpiohs->high_ip.u32, pin_channel, 1);
set_gpio_bit(gpiohs->high_ie.u32, pin_channel, 1);
}
if (IrqTable[pin_channel].hdr) {
IrqTable[pin_channel].hdr(IrqTable[pin_channel].args);
}
}
static uint32 GpioIrqRegister(int32 pin_channel, int32 mode, void (*hdr)(void *args), void *args)
{
IrqTable[pin_channel].hdr = hdr;
IrqTable[pin_channel].args = args;
switch (mode)
{
case GPIO_IRQ_EDGE_RISING:
IrqTable[pin_channel].edge = GPIO_PE_RISING;
break;
case GPIO_IRQ_EDGE_FALLING:
IrqTable[pin_channel].edge = GPIO_PE_FALLING;
break;
case GPIO_IRQ_EDGE_BOTH:
IrqTable[pin_channel].edge = GPIO_PE_BOTH;
break;
case GPIO_IRQ_LEVEL_HIGH:
IrqTable[pin_channel].edge = GPIO_PE_LOW;
break;
case GPIO_IRQ_LEVEL_LOW:
IrqTable[pin_channel].edge = GPIO_PE_HIGH;
break;
default:
break;
}
gpiohs_set_pin_edge(pin_channel, IrqTable[pin_channel].edge);
isrManager.done->registerIrq(IRQN_GPIOHS0_INTERRUPT + pin_channel, pin_irq, NONE);
return EOK;
}
static uint32 GpioIrqFree(int32 pin_channel)
{
IrqTable[pin_channel].hdr = NONE;
IrqTable[pin_channel].args = NONE;
return EOK;
}
static uint32 GpioIrqEnable(int32 pin_channel)
{
isrManager.done->enableIrq(IRQN_GPIOHS0_INTERRUPT + pin_channel);
return EOK;
}
static uint32 GpioIrqDisable(int32 pin_channel)
{
isrManager.done->disableIrq(IRQN_GPIOHS0_INTERRUPT + pin_channel);
return EOK;
}
static uint32 PinConfigure(struct PinParam *param)
{
NULL_PARAM_CHECK(param);
int ret = EOK;
int pin_channel = GetPinChannel(param->pin);
if (pin_channel == -1) {
pin_channel = AllocPinChannel(param->pin);
if (pin_channel == -1) {
return ERROR;
}
}
switch (param->cmd)
{
case GPIO_CONFIG_MODE:
GpioConfigMode(param->mode, pin_channel);
break;
case GPIO_IRQ_REGISTER:
ret = GpioIrqRegister(pin_channel,param->irq_set.irq_mode,param->irq_set.hdr,param->irq_set.args);
break;
case GPIO_IRQ_FREE:
ret = GpioIrqFree(pin_channel);
break;
case GPIO_IRQ_ENABLE:
ret = GpioIrqEnable(pin_channel);
break;
case GPIO_IRQ_DISABLE:
ret = GpioIrqDisable(pin_channel);
break;
default:
ret = -EINVALED;
break;
}
return ret;
}
static uint32 GpioDrvConfigure(void *drv, struct BusConfigureInfo *configure_info)
{
NULL_PARAM_CHECK(drv);
NULL_PARAM_CHECK(configure_info);
x_err_t ret = EOK;
struct PinParam *param;
switch (configure_info->configure_cmd)
{
case OPE_CFG:
param = (struct PinParam *)configure_info->private_data;
ret = PinConfigure(param);
break;
default:
break;
}
return ret;
}
uint32 PinWrite(void *dev, struct BusBlockWriteParam *write_param)
{
NULL_PARAM_CHECK(dev);
NULL_PARAM_CHECK(write_param);
struct PinStat *pinstat = (struct PinStat *)write_param->buffer;
int pin_channel = GetPinChannel(pinstat->pin);
if (pin_channel == -1) {
SYS_ERR("pin %d not set mode", pinstat->pin);
return ERROR;
}
gpiohs_set_pin(pin_channel, pinstat->val == GPIO_HIGH ? GPIO_PV_HIGH : GPIO_PV_LOW);
}
uint32 PinRead(void *dev, struct BusBlockReadParam *read_param)
{
NULL_PARAM_CHECK(dev);
NULL_PARAM_CHECK(read_param);
struct PinStat *pinstat = (struct PinStat *)read_param->buffer;
int pin_channel = GetPinChannel(pinstat->pin);
if (pin_channel == -1) {
SYS_ERR("pin %d not set mode", pinstat->pin);
return ERROR;
}
if (gpiohs_get_pin(pin_channel) == GPIO_PV_HIGH){
pinstat->val = GPIO_HIGH;
return GPIO_HIGH;
} else {
pinstat->val = GPIO_LOW;
return GPIO_LOW;
}
}
static const struct PinDevDone dev_done =
{
.open = NONE,
.close = NONE,
.write = PinWrite,
.read = PinRead,
};
int HwGpioInit(void)
{
x_err_t ret = EOK;
static struct PinBus pin;
memset(pin_alloc_table, -1, sizeof pin_alloc_table);
free_pin = GPIO_ALLOC_START;
ret = PinBusInit(&pin, PIN_BUS_NAME);
if (ret != EOK) {
KPrintf("gpio bus init error %d\n", ret);
return ERROR;
}
static struct PinDriver drv;
drv.configure = &GpioDrvConfigure;
ret = PinDriverInit(&drv, PIN_DRIVER_NAME, NONE);
if (ret != EOK) {
KPrintf("pin driver init error %d\n", ret);
return ERROR;
}
ret = PinDriverAttachToBus(PIN_DRIVER_NAME, PIN_BUS_NAME);
if (ret != EOK) {
KPrintf("pin driver attach error %d\n", ret);
return ERROR;
}
static struct PinHardwareDevice dev;
dev.dev_done = &dev_done;
ret = PinDeviceRegister(&dev, NONE, PIN_DEVICE_NAME);
if (ret != EOK) {
KPrintf("pin device register error %d\n", ret);
return ERROR;
}
ret = PinDeviceAttachToBus(PIN_DEVICE_NAME, PIN_BUS_NAME);
if (ret != EOK) {
KPrintf("pin device register error %d\n", ret);
return ERROR;
}
return ret;
}

View File

@ -0,0 +1,160 @@
/*
* Copyright (c) 2006-2018, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2019-03-19 ZYH first version
*/
/**
* @file drv_io_config.c
* @brief support kd233-board io configure
* @version 1.0
* @author AIIT XUOS Lab
* @date 2021-04-25
*/
/*************************************************
File name: drv_io_config.c
Description: support kd233-board io configure
Others: take RT-Thread v4.0.2/bsp/k210/driver/drv_io_config.c for references
https://github.com/RT-Thread/rt-thread/tree/v4.0.2
History:
1. Date: 2021-04-25
Author: AIIT XUOS Lab
Modification: support kd233-board io configure
*************************************************/
#include <xiuos.h>
#include <fpioa.h>
#include "drv_io_config.h"
#include <sysctl.h>
//#define LED_TEST
#define HS_GPIO(n) (FUNC_GPIOHS0 + n)
#define IOCONFIG(pin,func) {pin, func, #func}
static struct io_config
{
int io_num;
fpioa_function_t func;
const char * FuncName;
} io_config[] =
{
#ifdef BSP_USING_LCD
IOCONFIG(BSP_LCD_CS_PIN, FUNC_SPI0_SS0),
IOCONFIG(BSP_LCD_WR_PIN, FUNC_SPI0_SCLK),
IOCONFIG(BSP_LCD_DC_PIN, HS_GPIO(LCD_DC_PIN)),
#endif
#ifdef BSP_USING_CAMERA
IOCONFIG(BSP_CAMERA_SCCB_SDA_PIN, FUNC_SCCB_SDA),
IOCONFIG(BSP_CAMERA_SCCB_SCLK_PIN, FUNC_SCCB_SCLK),
IOCONFIG(BSP_CAMERA_CMOS_RST_PIN, FUNC_CMOS_RST),
IOCONFIG(BSP_CAMERA_CMOS_VSYNC_PIN, FUNC_CMOS_VSYNC),
IOCONFIG(BSP_CAMERA_CMOS_PWDN_PIN, FUNC_CMOS_PWDN),
IOCONFIG(BSP_CAMERA_CMOS_XCLK_PIN, FUNC_CMOS_XCLK),
IOCONFIG(BSP_CAMERA_CMOS_PCLK_PIN, FUNC_CMOS_PCLK),
IOCONFIG(BSP_CAMERA_CMOS_HREF_PIN, FUNC_CMOS_HREF),
#endif
#ifdef BSP_USING_SPI1
IOCONFIG(BSP_SPI1_CLK_PIN, FUNC_SPI1_SCLK),
IOCONFIG(BSP_SPI1_D0_PIN, FUNC_SPI1_D0),
IOCONFIG(BSP_SPI1_D1_PIN, FUNC_SPI1_D1),
#ifdef BSP_USING_SPI1_AS_QSPI
IOCONFIG(BSP_SPI1_D2_PIN, FUNC_SPI1_D2),
IOCONFIG(BSP_SPI1_D3_PIN, FUNC_SPI1_D3),
#endif
#ifdef BSP_SPI1_USING_SS0
IOCONFIG(BSP_SPI1_SS0_PIN, HS_GPIO(SPI1_CS0_PIN)),
#endif
#ifdef BSP_SPI1_USING_SS1
IOCONFIG(BSP_SPI1_SS1_PIN, HS_GPIO(SPI1_CS1_PIN)),
#endif
#ifdef BSP_SPI1_USING_SS2
IOCONFIG(BSP_SPI1_SS2_PIN, HS_GPIO(SPI1_CS2_PIN)),
#endif
#ifdef BSP_SPI1_USING_SS3
IOCONFIG(BSP_SPI1_SS3_PIN, HS_GPIO(SPI1_CS3_PIN)),
#endif
#endif
#ifdef BSP_USING_UART1
IOCONFIG(BSP_UART1_TXD_PIN, FUNC_UART1_TX),
IOCONFIG(BSP_UART1_RXD_PIN, FUNC_UART1_RX),
#endif
#ifdef BSP_USING_UART2
IOCONFIG(BSP_UART2_TXD_PIN, FUNC_UART2_TX),
IOCONFIG(BSP_UART2_RXD_PIN, FUNC_UART2_RX),
#endif
#ifdef BSP_USING_UART3
IOCONFIG(BSP_UART3_TXD_PIN, FUNC_UART3_TX),
IOCONFIG(BSP_UART3_RXD_PIN, FUNC_UART3_RX),
#endif
// #ifdef LED_TEST
// IOCONFIG(LED0, FUNC_GPIOHS0),
// #endif
IOCONFIG(18, FUNC_GPIOHS18),
IOCONFIG(19, FUNC_GPIOHS19),
};
static int PrintIoConfig()
{
int i;
KPrintf("IO Configuration Table\n");
KPrintf("┌───────┬────────────────────────┐\n");
KPrintf("│Pin │Function │\n");
KPrintf("├───────┼────────────────────────┤\n");
for(i = 0; i < sizeof io_config / sizeof io_config[0]; i++)
{
KPrintf("│%-2d │%-24.24s│\n", io_config[i].io_num, io_config[i].FuncName);
}
KPrintf("└───────┴────────────────────────┘\n");
return 0;
}
SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0)|SHELL_CMD_TYPE(SHELL_TYPE_CMD_FUNC)|SHELL_CMD_PARAM_NUM(0),
io,PrintIoConfig,print io config);
int IoConfigInit(void)
{
int count = sizeof(io_config) / sizeof(io_config[0]);
int i;
int ret = 0;
sysctl_set_power_mode(SYSCTL_POWER_BANK0, SYSCTL_POWER_V18);
sysctl_set_power_mode(SYSCTL_POWER_BANK1, SYSCTL_POWER_V18);
sysctl_set_power_mode(SYSCTL_POWER_BANK2, SYSCTL_POWER_V18);
#ifdef BSP_USING_UART2
// for IO-27/28
sysctl_set_power_mode(SYSCTL_POWER_BANK4, SYSCTL_POWER_V33);
#endif
#if defined(BSP_USING_UART1) || defined(BSP_USING_UART3)
// for IO-20~23
sysctl_set_power_mode(SYSCTL_POWER_BANK3, SYSCTL_POWER_V33);
#endif
for(i = 0; i < count; i++)
{
ret = FpioaSetFunction(io_config[i].io_num, io_config[i].func);
if(ret != 0)
return ret;
}
#if defined(BSP_USING_CAMERA) || defined(BSP_USING_LCD)
sysctl_set_spi0_dvp_data(1);
#endif
return ret;
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,89 @@
/* Copyright 2018 Canaan Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License"},
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* @file gpio.c
* @brief add from Canaan K210 SDK
* https://canaan-creative.com/developer
* @version 1.0
* @author AIIT XUOS Lab
* @date 2021-04-25
*/
#include "gpio.h"
#include "utils.h"
#include "fpioa.h"
#include "sysctl.h"
#define GPIO_MAX_PINNO 8
volatile gpio_t* const gpio = (volatile gpio_t*)GPIO_BASE_ADDR;
int gpio_init(void)
{
return sysctl_clock_enable(SYSCTL_CLOCK_GPIO);
}
void gpio_set_drive_mode(uint8_t pin, gpio_drive_mode_t mode)
{
configASSERT(pin < GPIO_MAX_PINNO);
int io_number = fpioa_get_io_by_function(FUNC_GPIO0 + pin);
configASSERT(io_number >= 0);
fpioa_pull_t pull;
uint32_t dir;
switch (mode)
{
case GPIO_DM_INPUT:
pull = FPIOA_PULL_NONE;
dir = 0;
break;
case GPIO_DM_INPUT_PULL_DOWN:
pull = FPIOA_PULL_DOWN;
dir = 0;
break;
case GPIO_DM_INPUT_PULL_UP:
pull = FPIOA_PULL_UP;
dir = 0;
break;
case GPIO_DM_OUTPUT:
pull = FPIOA_PULL_DOWN;
dir = 1;
break;
default:
configASSERT(!"GPIO drive mode is not supported.") break;
}
fpioa_set_io_pull(io_number, pull);
set_gpio_bit(gpio->direction.u32, pin, dir);
}
gpio_pin_value_t gpio_get_pin(uint8_t pin)
{
configASSERT(pin < GPIO_MAX_PINNO);
uint32_t dir = get_gpio_bit(gpio->direction.u32, pin);
volatile uint32_t *reg = dir ? gpio->data_output.u32 : gpio->data_input.u32;
return get_gpio_bit(reg, pin);
}
void gpio_set_pin(uint8_t pin, gpio_pin_value_t value)
{
configASSERT(pin < GPIO_MAX_PINNO);
uint32_t dir = get_gpio_bit(gpio->direction.u32, pin);
volatile uint32_t *reg = dir ? gpio->data_output.u32 : gpio->data_input.u32;
configASSERT(dir == 1);
set_gpio_bit(reg, pin, value);
}

View File

@ -0,0 +1,228 @@
/* Copyright 2018 Canaan Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License"},
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* @file gpiohs.c
* @brief add from Canaan K210 SDK
* https://canaan-creative.com/developer
* @version 1.0
* @author AIIT XUOS Lab
* @date 2021-04-25
*/
#include "gpiohs.h"
#include "utils.h"
#include "fpioa.h"
#include "sysctl.h"
#define GPIOHS_MAX_PINNO 32
volatile gpiohs_t* const gpiohs = (volatile gpiohs_t*)GPIOHS_BASE_ADDR;
typedef struct _gpiohs_pin_instance
{
size_t pin;
GpioPinEdgeT edge;
void (*callback)();
plic_irq_callback_t gpiohs_callback;
void *context;
} gpiohs_pin_instance_t;
static gpiohs_pin_instance_t pin_instance[32];
void gpiohs_set_drive_mode(uint8_t pin, gpio_drive_mode_t mode)
{
configASSERT(pin < GPIOHS_MAX_PINNO);
int io_number = fpioa_get_io_by_function(FUNC_GPIOHS0 + pin);
configASSERT(io_number >= 0);
fpioa_pull_t pull;
uint32_t dir;
switch (mode)
{
case GPIO_DM_INPUT:
pull = FPIOA_PULL_NONE;
dir = 0;
break;
case GPIO_DM_INPUT_PULL_DOWN:
pull = FPIOA_PULL_DOWN;
dir = 0;
break;
case GPIO_DM_INPUT_PULL_UP:
pull = FPIOA_PULL_UP;
dir = 0;
break;
case GPIO_DM_OUTPUT:
pull = FPIOA_PULL_DOWN;
dir = 1;
break;
default:
configASSERT(!"GPIO drive mode is not supported.") break;
}
fpioa_set_io_pull(io_number, pull);
volatile uint32_t *reg = dir ? gpiohs->output_en.u32 : gpiohs->input_en.u32;
volatile uint32_t *reg_d = !dir ? gpiohs->output_en.u32 : gpiohs->input_en.u32;
set_gpio_bit(reg_d, pin, 0);
set_gpio_bit(reg, pin, 1);
}
gpio_pin_value_t gpiohs_get_pin(uint8_t pin)
{
configASSERT(pin < GPIOHS_MAX_PINNO);
return get_gpio_bit(gpiohs->input_val.u32, pin);
}
void gpiohs_set_pin(uint8_t pin, gpio_pin_value_t value)
{
configASSERT(pin < GPIOHS_MAX_PINNO);
set_gpio_bit(gpiohs->output_val.u32, pin, value);
}
void gpiohs_set_pin_edge(uint8_t pin, GpioPinEdgeT edge)
{
set_gpio_bit(gpiohs->rise_ie.u32, pin, 0);
set_gpio_bit(gpiohs->rise_ip.u32, pin, 1);
set_gpio_bit(gpiohs->fall_ie.u32, pin, 0);
set_gpio_bit(gpiohs->fall_ip.u32, pin, 1);
set_gpio_bit(gpiohs->low_ie.u32, pin, 0);
set_gpio_bit(gpiohs->low_ip.u32, pin, 1);
set_gpio_bit(gpiohs->high_ie.u32, pin, 0);
set_gpio_bit(gpiohs->high_ip.u32, pin, 1);
if(edge & GPIO_PE_FALLING)
{
set_gpio_bit(gpiohs->fall_ie.u32, pin, 1);
}
else
{
set_gpio_bit(gpiohs->fall_ie.u32, pin, 0);
}
if(edge & GPIO_PE_RISING)
{
set_gpio_bit(gpiohs->rise_ie.u32, pin, 1);
}
else
{
set_gpio_bit(gpiohs->rise_ie.u32, pin, 0);
}
if(edge & GPIO_PE_LOW)
{
set_gpio_bit(gpiohs->low_ie.u32, pin, 1);
}
else
{
set_gpio_bit(gpiohs->low_ie.u32, pin, 0);
}
if(edge & GPIO_PE_HIGH)
{
set_gpio_bit(gpiohs->high_ie.u32, pin, 1);
}
else
{
set_gpio_bit(gpiohs->high_ie.u32, pin, 0);
}
pin_instance[pin].edge = edge;
}
int gpiohs_pin_onchange_isr(void *userdata)
{
gpiohs_pin_instance_t *ctx = (gpiohs_pin_instance_t *)userdata;
size_t pin = ctx->pin;
if(ctx->edge & GPIO_PE_FALLING)
{
set_gpio_bit(gpiohs->fall_ie.u32, pin, 0);
set_gpio_bit(gpiohs->fall_ip.u32, pin, 1);
set_gpio_bit(gpiohs->fall_ie.u32, pin, 1);
}
if(ctx->edge & GPIO_PE_RISING)
{
set_gpio_bit(gpiohs->rise_ie.u32, pin, 0);
set_gpio_bit(gpiohs->rise_ip.u32, pin, 1);
set_gpio_bit(gpiohs->rise_ie.u32, pin, 1);
}
if(ctx->edge & GPIO_PE_LOW)
{
set_gpio_bit(gpiohs->low_ie.u32, pin, 0);
set_gpio_bit(gpiohs->low_ip.u32, pin, 1);
set_gpio_bit(gpiohs->low_ie.u32, pin, 1);
}
if(ctx->edge & GPIO_PE_HIGH)
{
set_gpio_bit(gpiohs->high_ie.u32, pin, 0);
set_gpio_bit(gpiohs->high_ip.u32, pin, 1);
set_gpio_bit(gpiohs->high_ie.u32, pin, 1);
}
if (ctx->callback)
ctx->callback();
if(ctx->gpiohs_callback)
ctx->gpiohs_callback(ctx->context);
return 0;
}
void gpiohs_set_irq(uint8_t pin, uint32_t priority, void (*func)())
{
pin_instance[pin].pin = pin;
pin_instance[pin].callback = func;
plic_set_priority(IRQN_GPIOHS0_INTERRUPT + pin, priority);
plic_irq_register(IRQN_GPIOHS0_INTERRUPT + pin, gpiohs_pin_onchange_isr, &(pin_instance[pin]));
plic_irq_enable(IRQN_GPIOHS0_INTERRUPT + pin);
}
void gpiohs_irq_register(uint8_t pin, uint32_t priority, plic_irq_callback_t callback, void *ctx)
{
pin_instance[pin].pin = pin;
pin_instance[pin].gpiohs_callback = callback;
pin_instance[pin].context = ctx;
plic_set_priority(IRQN_GPIOHS0_INTERRUPT + pin, priority);
plic_irq_register(IRQN_GPIOHS0_INTERRUPT + pin, gpiohs_pin_onchange_isr, &(pin_instance[pin]));
plic_irq_enable(IRQN_GPIOHS0_INTERRUPT + pin);
}
void gpiohs_irq_unregister(uint8_t pin)
{
pin_instance[pin] = (gpiohs_pin_instance_t){
.callback = NULL,
.gpiohs_callback = NULL,
.context = NULL,
};
set_gpio_bit(gpiohs->rise_ie.u32, pin, 0);
set_gpio_bit(gpiohs->fall_ie.u32, pin, 0);
set_gpio_bit(gpiohs->low_ie.u32, pin, 0);
set_gpio_bit(gpiohs->high_ie.u32, pin, 0);
plic_irq_unregister(IRQN_GPIOHS0_INTERRUPT + pin);
}
void gpiohs_irq_disable(size_t pin)
{
plic_irq_disable(IRQN_GPIOHS0_INTERRUPT + pin);
}

View File

@ -0,0 +1,54 @@
/* Copyright 2018 Canaan Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License"},
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* @file utils.c
* @brief add from Canaan K210 SDK
* https://canaan-creative.com/developer
* @version 1.0
* @author AIIT XUOS Lab
* @date 2021-04-25
*/
#include <stddef.h>
#include "encoding.h"
#include "utils.h"
void set_bit(volatile uint32_t *bits, uint32_t mask, uint32_t value)
{
uint32_t org = (*bits) & ~mask;
*bits = org | (value & mask);
}
void set_bit_offset(volatile uint32_t *bits, uint32_t mask, size_t offset, uint32_t value)
{
set_bit(bits, mask << offset, value << offset);
}
void set_gpio_bit(volatile uint32_t *bits, size_t offset, uint32_t value)
{
set_bit_offset(bits, 1, offset, value);
}
uint32_t get_bit(volatile uint32_t *bits, uint32_t mask, size_t offset)
{
return ((*bits) & (mask << offset)) >> offset;
}
uint32_t get_gpio_bit(volatile uint32_t *bits, size_t offset)
{
return get_bit(bits, 1, offset);
}

View File

@ -0,0 +1,17 @@
if BSP_USING_I2C
config BSP_I2C_SDA
int "SDA pin number for I2C"
default 15
config BSP_I2C_SCL
int "SCLK pin number for I2C"
default 17
config I2C_BUS_NAME_1
string "i2c bus 1 name"
default "i2c1"
config I2C_DRV_NAME_1
string "i2c bus 1 driver name"
default "i2c1_drv"
config I2C_1_DEVICE_NAME_0
string "i2c bus 1 device 0 name"
default "i2c1_dev0"
endif

View File

@ -0,0 +1,6 @@
SRC_FILES := connect_i2c.c hardware_i2c.c
include $(KERNEL_ROOT)/compiler.mk

View File

@ -0,0 +1,596 @@
/*
* Copyright (c) 2020 RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2012-04-25 weety first version
*/
/**
* @file connect_i2c.c
* @brief support kd233-board i2c function and register to bus framework
* @version 1.0
* @author AIIT XUOS Lab
* @date 2021-04-25
*/
/*************************************************
File name: connect_i2c.c
Description: support kd233-board i2c configure and i2c bus register function
Others: take RT-Thread v4.0.2/components/drivers/i2c/i2c-bit-ops.c for references
https://github.com/RT-Thread/rt-thread/tree/v4.0.2
History:
1. Date: 2021-04-25
Author: AIIT XUOS Lab
Modification:
1. support kd233-board i2c bit configure, write and read
2. support kd233-board i2c bus device and driver register
*************************************************/
#include <board.h>
#include "gpio_common.h"
#include"fpioa.h"
#include "connect_i2c.h"
#include <sleep.h>
#include "sysctl.h"
#include "gpio.h"
#ifndef BSP_USING_I2C1
#define BSP_USING_I2C1
#endif
#define I2C_SDA_FUNC_GPIO 3
#define I2C_SCL_FUNC_GPIO 4
static I2cBusParam i2c_bus_param =
{
I2C_SDA_FUNC_GPIO,
I2C_SCL_FUNC_GPIO,
};
#define SET_SDA(done, val) done->SetSdaState(done->data, val)
#define SET_SCL(done, val) done->SetSclState(done->data, val)
#define GET_SDA(done) done->GetSdaState(done->data)
#define GET_SCL(done) done->GetSclState(done->data)
#define SdaLow(done) SET_SDA(done, 0)
#define SdaHigh(done) SET_SDA(done, 1)
#define SclLow(done) SET_SCL(done, 0)
void I2cGpioInit(const I2cBusParam *bus_param)
{
gpio_init ();
FpioaSetFunction(BSP_I2C_SDA , FUNC_GPIO3 );//RISC-V FPIOA CFG
FpioaSetFunction(BSP_I2C_SCL , FUNC_GPIO4 );//RISC-V FPIOA CFG
gpio_set_drive_mode(bus_param->i2c_sda_pin , GPIO_DM_OUTPUT );
gpio_set_drive_mode(bus_param->i2c_scl_pin, GPIO_DM_OUTPUT );
gpio_set_pin(bus_param->i2c_sda_pin , GPIO_PV_HIGH );
gpio_set_pin(bus_param->i2c_scl_pin , GPIO_PV_HIGH );
}
static void SetSdaState(void *data, uint8 sda_state)
{
I2cBusParam *bus_param = (I2cBusParam *)data;
if (sda_state) {
gpio_set_drive_mode(bus_param->i2c_sda_pin, GPIO_DM_OUTPUT );
gpio_set_pin(bus_param->i2c_sda_pin , GPIO_PV_HIGH );
} else {
gpio_set_drive_mode(bus_param->i2c_sda_pin, GPIO_DM_OUTPUT );
gpio_set_pin(bus_param->i2c_sda_pin , GPIO_PV_LOW );
}
}
static void SetSclState(void *data, uint8 scl_state)
{
I2cBusParam *bus_param = (I2cBusParam *)data;
if (scl_state) {
gpio_set_drive_mode(bus_param->i2c_scl_pin, GPIO_DM_OUTPUT );
gpio_set_pin(bus_param->i2c_scl_pin , GPIO_PV_HIGH );
} else {
gpio_set_drive_mode(bus_param->i2c_scl_pin, GPIO_DM_OUTPUT );
gpio_set_pin(bus_param->i2c_scl_pin , GPIO_PV_LOW );
}
}
static uint8 GetSdaState(void *data)
{
I2cBusParam *bus_param = (I2cBusParam *)data;
gpio_set_drive_mode (bus_param->i2c_sda_pin, GPIO_DM_INPUT_PULL_UP );
return gpio_get_pin(bus_param->i2c_sda_pin);
}
static uint8 GetSclState(void *data)
{
I2cBusParam *bus_param = (I2cBusParam *)data;
gpio_set_drive_mode (bus_param->i2c_scl_pin, GPIO_DM_INPUT_PULL_UP );
return gpio_get_pin(bus_param->i2c_scl_pin);
}
static const struct I2cHalDrvDone I2cDrvDone =
{
.data = (&i2c_bus_param),
.SetSdaState = SetSdaState,
.SetSclState = SetSclState,
.GetSdaState = GetSdaState,
.GetSclState = GetSclState,
.udelay = usleep,
.delay_us = 1,
.timeout = 100
};
static x_err_t I2cBusReset(const I2cBusParam *bus_param)
{
int32 i = 0;
gpio_set_drive_mode(bus_param->i2c_sda_pin, GPIO_DM_INPUT_PULL_UP );
if (GPIO_LOW == gpio_get_pin(bus_param->i2c_sda_pin)) {
while (i++ < 9) {
gpio_set_drive_mode(bus_param->i2c_scl_pin, GPIO_DM_OUTPUT );
gpio_set_pin(bus_param->i2c_scl_pin , GPIO_PV_HIGH );
usleep(100);
gpio_set_pin(bus_param->i2c_scl_pin , GPIO_PV_LOW );
usleep(100);
}
}
gpio_set_drive_mode(bus_param->i2c_sda_pin, GPIO_DM_INPUT_PULL_UP );
if (GPIO_LOW == gpio_get_pin(bus_param->i2c_sda_pin)) {
return -ERROR;
}
return EOK;
}
static __inline void I2cDelay(struct I2cHalDrvDone *done)
{
done->udelay((done->delay_us + 1) >> 1);
}
static __inline void I2cDelay2(struct I2cHalDrvDone *done)
{
done->udelay(done->delay_us);
}
static x_err_t SclHigh(struct I2cHalDrvDone *done)
{
x_ticks_t start;
SET_SCL(done, 1);
if (!done->GetSclState)
goto done;
start = CurrentTicksGain();
while (!GET_SCL(done)) {
if ((CurrentTicksGain() - start) > done->timeout)
return -ETIMEOUT;
DelayKTask((done->timeout + 1) >> 1);
}
done:
I2cDelay(done);
return EOK;
}
static void I2cStart(struct I2cHalDrvDone *done)
{
SdaLow(done);
I2cDelay(done);
SclLow(done);
}
static void I2cRestart(struct I2cHalDrvDone *done)
{
SdaHigh(done);
SclHigh(done);
I2cDelay(done);
SdaLow(done);
I2cDelay(done);
SclLow(done);
}
static void I2cStop(struct I2cHalDrvDone *done)
{
SdaLow(done);
I2cDelay(done);
SclHigh(done);
I2cDelay(done);
SdaHigh(done);
I2cDelay2(done);
}
static __inline x_bool I2cWaitack(struct I2cHalDrvDone *done)
{
x_bool ack;
SdaHigh(done);
GET_SDA(done);
I2cDelay(done);
if (SclHigh(done) < 0) {
KPrintf("wait ack timeout");
return -ETIMEOUT;
}
ack = !GET_SDA(done);
SclLow(done);
return ack;
}
static int32 I2cWriteb(struct I2cBus *bus, uint8 data)
{
int32 i;
uint8 bit;
struct I2cHalDrvDone *done = (struct I2cHalDrvDone *)bus->private_data;
for (i = 7; i >= 0; i--) {
SclLow(done);
bit = (data >> i) & 1;
SET_SDA(done, bit);
I2cDelay(done);
if (SclHigh(done) < 0) {
KPrintf("I2cWriteb: 0x%02x, "
"wait scl pin high timeout at bit %d",
data, i);
return -ETIMEOUT;
}
}
SclLow(done);
I2cDelay(done);
return I2cWaitack(done);
}
static int32 I2cReadb(struct I2cBus *bus)
{
uint8 i;
uint8 data = 0;
struct I2cHalDrvDone *done = (struct I2cHalDrvDone *)bus->private_data;
SdaHigh(done);
GET_SDA(done);
I2cDelay(done);
for (i = 0; i < 8; i++) {
data <<= 1;
if (SclHigh(done) < 0) {
KPrintf("I2cReadb: wait scl pin high "
"timeout at bit %d", 7 - i);
return -ETIMEOUT;
}
if (GET_SDA(done))
data |= 1;
SclLow(done);
I2cDelay2(done);
}
return data;
}
static x_size_t I2cSendBytes(struct I2cBus *bus, struct I2cDataStandard *msg)
{
int32 ret;
x_size_t bytes = 0;
const uint8 *ptr = msg->buf;
int32 count = msg->len;
uint16 ignore_nack = msg->flags & I2C_IGNORE_NACK;
while (count > 0) {
ret = I2cWriteb(bus, *ptr);
if ((ret > 0) || (ignore_nack && (ret == 0))) {
count --;
ptr ++;
bytes ++;
} else if (ret == 0) {
return 0;
} else {
KPrintf("send bytes: error %d", ret);
return ret;
}
}
return bytes;
}
static x_err_t I2cSendAckOrNack(struct I2cBus *bus, int ack)
{
struct I2cHalDrvDone *done = (struct I2cHalDrvDone *)bus->private_data;
if (ack)
SET_SDA(done, 0);
I2cDelay(done);
if (SclHigh(done) < 0) {
KPrintf("ACK or NACK timeout.");
return -ETIMEOUT;
}
SclLow(done);
return EOK;
}
static x_size_t I2cRecvBytes(struct I2cBus *bus, struct I2cDataStandard *msg)
{
int32 val;
int32 bytes = 0;
uint8 *ptr = msg->buf;
int32 count = msg->len;
const uint32 flags = msg->flags;
while (count > 0) {
val = I2cReadb(bus);
if (val >= 0) {
*ptr = val;
bytes ++;
} else {
break;
}
ptr ++;
count --;
if (!(flags & I2C_NO_READ_ACK)) {
val = I2cSendAckOrNack(bus, count);
if (val < 0)
return val;
}
}
return bytes;
}
static int32 I2cSendAddress(struct I2cBus *bus, uint8 addr, int32 retries)
{
struct I2cHalDrvDone *done = (struct I2cHalDrvDone *)bus->private_data;
int32 i;
x_err_t ret = 0;
for (i = 0; i <= retries; i++) {
ret = I2cWriteb(bus, addr);
if (ret == 1 || i == retries)
break;
I2cStop(done);
I2cDelay2(done);
I2cStart(done);
}
return ret;
}
static x_err_t I2cBitSendAddress(struct I2cBus *bus, struct I2cDataStandard *msg)
{
uint16 flags = msg->flags;
uint16 ignore_nack = msg->flags & I2C_IGNORE_NACK;
struct I2cHalDrvDone *done = (struct I2cHalDrvDone *)bus->private_data;
uint8 addr1, addr2;
int32 retries;
x_err_t ret;
retries = ignore_nack ? 0 : msg->retries;
if (flags & I2C_ADDR_10BIT) {
addr1 = 0xf0 | ((msg->addr >> 7) & 0x06);
addr2 = msg->addr & 0xff;
ret = I2cSendAddress(bus, addr1, retries);
if ((ret != 1) && !ignore_nack) {
return -EPIO;
}
ret = I2cWriteb(bus, addr2);
if ((ret != 1) && !ignore_nack) {
return -EPIO;
}
if (flags & I2C_RD) {
I2cRestart(done);
addr1 |= 0x01;
ret = I2cSendAddress(bus, addr1, retries);
if ((ret != 1) && !ignore_nack) {
return -EPIO;
}
}
} else {
addr1 = msg->addr << 1;
if (flags & I2C_RD)
addr1 |= 1;
ret = I2cSendAddress(bus, addr1, retries);
if ((ret != 1) && !ignore_nack)
return -EPIO;
}
return EOK;
}
static uint32 I2cWriteData(struct I2cHardwareDevice *i2c_dev, struct I2cDataStandard *msg)
{
struct I2cBus *bus = (struct I2cBus *)i2c_dev->haldev.owner_bus;
bus->private_data = i2c_dev->haldev.owner_bus->private_data;
struct I2cHalDrvDone *done = (struct I2cHalDrvDone *)bus->private_data;
int32 ret;
int32 i = 0;
uint16 ignore_nack;
I2cStart(done);
while (NONE != msg) {
ignore_nack = msg->flags & I2C_IGNORE_NACK;
if (!(msg->flags & I2C_NO_START)) {
if (i) {
I2cRestart(done);
}
ret = I2cBitSendAddress(bus, msg);
if ((ret != EOK) && !ignore_nack) {
goto out;
}
}
if (msg->flags & I2C_WR) {
ret = I2cSendBytes(bus, msg);
if (ret >= 1)
//KPrintf("write %d byte%s", ret, ret == 1 ? "" : "s");
if (ret < msg->len) {
if (ret >= 0)
ret = -ERROR;
goto out;
}
}
msg = msg->next;
i++;
}
ret = i;
out:
I2cStop(done);
return ret;
}
static uint32 I2cReadData(struct I2cHardwareDevice *i2c_dev, struct I2cDataStandard *msg)
{
struct I2cBus *bus = (struct I2cBus *)i2c_dev->haldev.owner_bus;
bus->private_data = i2c_dev->haldev.owner_bus->private_data;
struct I2cHalDrvDone *done = (struct I2cHalDrvDone *)bus->private_data;
int32 ret;
int32 i = 0;
uint16 ignore_nack;
I2cStart(done);
while (NONE != msg) {
ignore_nack = msg->flags & I2C_IGNORE_NACK;
if (!(msg->flags & I2C_NO_START)) {
if (i) {
I2cRestart(done);
}
ret = I2cBitSendAddress(bus, msg);
if ((ret != EOK) && !ignore_nack) {
goto out;
}
}
if (msg->flags & I2C_RD) {
ret = I2cRecvBytes(bus, msg);
if (ret >= 1)
//KPrintf("read %d byte%s", ret, ret == 1 ? "" : "s");
if (ret < msg->len) {
if (ret >= 0)
ret = -EPIO;
goto out;
}
}
msg = msg->next;
i++;
}
ret = i;
out:
I2cStop(done);
return ret;
}
/*manage the i2c device operations*/
static const struct I2cDevDone i2c_dev_done =
{
.open = NONE,
.close = NONE,
.write = I2cWriteData,
.read = I2cReadData,
};
/*Init i2c bus*/
static int BoardI2cBusInit(struct I2cBus *i2c_bus, struct I2cDriver *i2c_driver)
{
x_err_t ret = EOK;
/*Init the i2c bus */
i2c_bus->private_data = (void *)&I2cDrvDone;
ret = I2cBusInit(i2c_bus, I2C_BUS_NAME_1);
if (EOK != ret) {
KPrintf("board_i2c_init I2cBusInit error %d\n", ret);
return ERROR;
}
/*Init the i2c driver*/
i2c_driver->private_data = (void *)&I2cDrvDone;
ret = I2cDriverInit(i2c_driver, I2C_DRV_NAME_1);
if (EOK != ret) {
KPrintf("board_i2c_init I2cDriverInit error %d\n", ret);
return ERROR;
}
/*Attach the i2c driver to the i2c bus*/
ret = I2cDriverAttachToBus(I2C_DRV_NAME_1, I2C_BUS_NAME_1);
if (EOK != ret) {
KPrintf("board_i2c_init I2cDriverAttachToBus error %d\n", ret);
return ERROR;
}
return ret;
}
/*Attach the i2c device to the i2c bus*/
static int BoardI2cDevBend(void)
{
x_err_t ret = EOK;
static struct I2cHardwareDevice i2c_device0;
memset(&i2c_device0, 0, sizeof(struct I2cHardwareDevice));
i2c_device0.i2c_dev_done = &i2c_dev_done;
ret = I2cDeviceRegister(&i2c_device0, NONE, I2C_1_DEVICE_NAME_0);
if (EOK != ret) {
KPrintf("board_i2c_init I2cDeviceInit device %s error %d\n", I2C_1_DEVICE_NAME_0, ret);
return ERROR;
}
ret = I2cDeviceAttachToBus(I2C_1_DEVICE_NAME_0, I2C_BUS_NAME_1);
if (EOK != ret) {
KPrintf("board_i2c_init I2cDeviceAttachToBus device %s error %d\n", I2C_1_DEVICE_NAME_0, ret);
return ERROR;
}
return ret;
}
/*KD233 BOARD I2C INIT*/
int HwI2cInit(void)
{
x_err_t ret = EOK;
static struct I2cBus i2c_bus;
memset(&i2c_bus, 0, sizeof(struct I2cBus));
static struct I2cDriver i2c_driver;
memset(&i2c_driver, 0, sizeof(struct I2cDriver));
#ifdef BSP_USING_I2C1
I2cGpioInit(&i2c_bus_param);
ret = BoardI2cBusInit(&i2c_bus, &i2c_driver);
if (EOK != ret) {
KPrintf("board_i2c_Init error ret %u\n", ret);
return ERROR;
}
ret = BoardI2cDevBend();
if (EOK != ret) {
KPrintf("board_i2c_Init error ret %u\n", ret);
return ERROR;
}
I2cBusReset(&i2c_bus_param);
#endif
return ret;
}

View File

@ -0,0 +1,371 @@
/* Copyright 2018 Canaan Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* @file hardware_i2c.c
* @brief add from Canaan k210 SDK
* https://canaan-creative.com/developer
* @version 1.0
* @author AIIT XUOS Lab
* @date 2021-04-25
*/
#include <stddef.h>
#include "hardware_i2c.h"
#include "utils.h"
#include "fpioa.h"
#include "platform.h"
#include "stdlib.h"
#include "string.h"
#include "sysctl.h"
#include "bsp.h"
typedef struct _i2c_slave_instance
{
uint32_t i2c_num;
const i2c_slave_handler_t *slave_handler;
} i2c_slave_instance_t;
static i2c_slave_instance_t slave_instance[I2C_MAX_NUM];
typedef struct _i2c_instance
{
i2c_device_number_t i2c_num;
i2c_transfer_mode_t TransferMode;
dmac_channel_number_t dmac_channel;
plic_instance_t i2c_int_instance;
spinlock_t lock;
} i2c_instance_t;
static i2c_instance_t g_i2c_instance[3];
volatile i2c_t* const i2c[3] =
{
(volatile i2c_t*)I2C0_BASE_ADDR,
(volatile i2c_t*)I2C1_BASE_ADDR,
(volatile i2c_t*)I2C2_BASE_ADDR
};
static void i2c_clk_init(i2c_device_number_t i2c_num)
{
configASSERT(i2c_num < I2C_MAX_NUM);
sysctl_clock_enable(SYSCTL_CLOCK_I2C0 + i2c_num);
sysctl_clock_set_threshold(SYSCTL_THRESHOLD_I2C0 + i2c_num, 3);
}
void i2c_init(i2c_device_number_t i2c_num, uint32_t slave_address, uint32_t address_width,
uint32_t i2c_clk)
{
configASSERT(i2c_num < I2C_MAX_NUM);
configASSERT(address_width == 7 || address_width == 10);
volatile i2c_t *i2c_adapter = i2c[i2c_num];
i2c_clk_init(i2c_num);
uint32_t v_i2c_freq = SysctlClockGetFreq(SYSCTL_CLOCK_I2C0 + i2c_num);
uint16_t v_period_clk_cnt = v_i2c_freq / i2c_clk / 2;
if(v_period_clk_cnt == 0)
v_period_clk_cnt = 1;
i2c_adapter->enable = 0;
i2c_adapter->con = I2C_CON_MASTER_MODE | I2C_CON_SLAVE_DISABLE | I2C_CON_RESTART_EN |
(address_width == 10 ? I2C_CON_10BITADDR_SLAVE : 0) | I2C_CON_SPEED(1);
i2c_adapter->ss_scl_hcnt = I2C_SS_SCL_HCNT_COUNT(v_period_clk_cnt);
i2c_adapter->ss_scl_lcnt = I2C_SS_SCL_LCNT_COUNT(v_period_clk_cnt);
i2c_adapter->tar = I2C_TAR_ADDRESS(slave_address);
i2c_adapter->intr_mask = 0;
i2c_adapter->dma_cr = 0x3;
i2c_adapter->dma_rdlr = 0;
i2c_adapter->dma_tdlr = 4;
i2c_adapter->enable = I2C_ENABLE_ENABLE;
}
static int i2c_slave_irq(void *userdata)
{
i2c_slave_instance_t *instance = (i2c_slave_instance_t *)userdata;
volatile i2c_t *i2c_adapter = i2c[instance->i2c_num];
uint32_t status = i2c_adapter->intr_stat;
if (status & I2C_INTR_STAT_START_DET)
{
instance->slave_handler->on_event(I2C_EV_START);
readl(&i2c_adapter->clr_start_det);
}
if (status & I2C_INTR_STAT_STOP_DET)
{
instance->slave_handler->on_event(I2C_EV_STOP);
readl(&i2c_adapter->clr_stop_det);
}
if (status & I2C_INTR_STAT_RX_FULL)
{
instance->slave_handler->on_receive(i2c_adapter->data_cmd);
}
if (status & I2C_INTR_STAT_RD_REQ)
{
i2c_adapter->data_cmd = instance->slave_handler->on_transmit();
readl(&i2c_adapter->clr_rd_req);
}
return 0;
}
void i2c_init_as_slave(i2c_device_number_t i2c_num, uint32_t slave_address, uint32_t address_width,
const i2c_slave_handler_t *handler)
{
configASSERT(address_width == 7 || address_width == 10);
volatile i2c_t *i2c_adapter = i2c[i2c_num];
slave_instance[i2c_num].i2c_num = i2c_num;
slave_instance[i2c_num].slave_handler = handler;
i2c_clk_init(i2c_num);
i2c_adapter->enable = 0;
i2c_adapter->con = (address_width == 10 ? I2C_CON_10BITADDR_SLAVE : 0) | I2C_CON_SPEED(1) | I2C_CON_STOP_DET_IFADDRESSED;
i2c_adapter->ss_scl_hcnt = I2C_SS_SCL_HCNT_COUNT(37);
i2c_adapter->ss_scl_lcnt = I2C_SS_SCL_LCNT_COUNT(40);
i2c_adapter->sar = I2C_SAR_ADDRESS(slave_address);
i2c_adapter->rx_tl = I2C_RX_TL_VALUE(0);
i2c_adapter->tx_tl = I2C_TX_TL_VALUE(0);
i2c_adapter->intr_mask = I2C_INTR_MASK_RX_FULL | I2C_INTR_MASK_START_DET | I2C_INTR_MASK_STOP_DET | I2C_INTR_MASK_RD_REQ;
plic_set_priority(IRQN_I2C0_INTERRUPT + i2c_num, 1);
plic_irq_register(IRQN_I2C0_INTERRUPT + i2c_num, i2c_slave_irq, slave_instance + i2c_num);
plic_irq_enable(IRQN_I2C0_INTERRUPT + i2c_num);
i2c_adapter->enable = I2C_ENABLE_ENABLE;
}
int i2c_send_data(i2c_device_number_t i2c_num, const uint8_t *SendBuf, size_t send_buf_len)
{
configASSERT(i2c_num < I2C_MAX_NUM);
volatile i2c_t* i2c_adapter = i2c[i2c_num];
size_t fifo_len, index;
i2c_adapter->clr_tx_abrt = i2c_adapter->clr_tx_abrt;
while (send_buf_len)
{
fifo_len = 8 - i2c_adapter->txflr;
fifo_len = send_buf_len < fifo_len ? send_buf_len : fifo_len;
for (index = 0; index < fifo_len; index++)
i2c_adapter->data_cmd = I2C_DATA_CMD_DATA(*SendBuf++);
if (i2c_adapter->tx_abrt_source != 0)
return 1;
send_buf_len -= fifo_len;
}
while ((i2c_adapter->status & I2C_STATUS_ACTIVITY) || !(i2c_adapter->status & I2C_STATUS_TFE))
;
if (i2c_adapter->tx_abrt_source != 0)
return 1;
return 0;
}
void i2c_send_data_dma(dmac_channel_number_t dma_channel_num, i2c_device_number_t i2c_num, const uint8_t *SendBuf,
size_t send_buf_len)
{
configASSERT(i2c_num < I2C_MAX_NUM);
volatile i2c_t* i2c_adapter = i2c[i2c_num];
i2c_adapter->clr_tx_abrt = i2c_adapter->clr_tx_abrt;
uint32_t *buf = malloc(send_buf_len * sizeof(uint32_t));
int i;
for (i = 0; i < send_buf_len; i++)
{
buf[i] = SendBuf[i];
}
sysctl_dma_select((sysctl_dma_channel_t)dma_channel_num, SYSCTL_DMA_SELECT_I2C0_TX_REQ + i2c_num * 2);
dmac_set_single_mode(dma_channel_num, buf, (void *)(&i2c_adapter->data_cmd), DMAC_ADDR_INCREMENT, DMAC_ADDR_NOCHANGE,
DMAC_MSIZE_4, DMAC_TRANS_WIDTH_32, send_buf_len);
dmac_wait_done(dma_channel_num);
free((void *)buf);
while ((i2c_adapter->status & I2C_STATUS_ACTIVITY) || !(i2c_adapter->status & I2C_STATUS_TFE))
{
if (i2c_adapter->tx_abrt_source != 0)
return;
}
}
int i2c_recv_data(i2c_device_number_t i2c_num, const uint8_t *SendBuf, size_t send_buf_len, uint8_t *receive_buf,
size_t receive_buf_len)
{
configASSERT(i2c_num < I2C_MAX_NUM);
size_t fifo_len, index;
size_t rx_len = receive_buf_len;
volatile i2c_t* i2c_adapter = i2c[i2c_num];
while (send_buf_len)
{
fifo_len = 8 - i2c_adapter->txflr;
fifo_len = send_buf_len < fifo_len ? send_buf_len : fifo_len;
for (index = 0; index < fifo_len; index++)
i2c_adapter->data_cmd = I2C_DATA_CMD_DATA(*SendBuf++);
if (i2c_adapter->tx_abrt_source != 0)
return 1;
send_buf_len -= fifo_len;
}
while (receive_buf_len || rx_len)
{
fifo_len = i2c_adapter->rxflr;
fifo_len = rx_len < fifo_len ? rx_len : fifo_len;
for (index = 0; index < fifo_len; index++)
*receive_buf++ = (uint8_t)i2c_adapter->data_cmd;
rx_len -= fifo_len;
fifo_len = 8 - i2c_adapter->txflr;
fifo_len = receive_buf_len < fifo_len ? receive_buf_len : fifo_len;
for (index = 0; index < fifo_len; index++)
i2c_adapter->data_cmd = I2C_DATA_CMD_CMD;
if (i2c_adapter->tx_abrt_source != 0)
return 1;
receive_buf_len -= fifo_len;
}
return 0;
}
void i2c_recv_data_dma(dmac_channel_number_t dma_send_channel_num, dmac_channel_number_t dma_receive_channel_num,
i2c_device_number_t i2c_num, const uint8_t *SendBuf, size_t send_buf_len,
uint8_t *receive_buf, size_t receive_buf_len)
{
configASSERT(i2c_num < I2C_MAX_NUM);
volatile i2c_t* i2c_adapter = i2c[i2c_num];
uint32_t *write_cmd = malloc(sizeof(uint32_t) * (send_buf_len + receive_buf_len));
size_t i;
for(i = 0; i < send_buf_len; i++)
write_cmd[i] = *SendBuf++;
for (i = 0; i < receive_buf_len; i++)
write_cmd[i + send_buf_len] = I2C_DATA_CMD_CMD;
sysctl_dma_select((sysctl_dma_channel_t)dma_send_channel_num, SYSCTL_DMA_SELECT_I2C0_TX_REQ + i2c_num * 2);
sysctl_dma_select((sysctl_dma_channel_t)dma_receive_channel_num, SYSCTL_DMA_SELECT_I2C0_RX_REQ + i2c_num * 2);
dmac_set_single_mode(dma_receive_channel_num, (void *)(&i2c_adapter->data_cmd), write_cmd, DMAC_ADDR_NOCHANGE,
DMAC_ADDR_INCREMENT,DMAC_MSIZE_1, DMAC_TRANS_WIDTH_32, receive_buf_len);
dmac_set_single_mode(dma_send_channel_num, write_cmd, (void *)(&i2c_adapter->data_cmd), DMAC_ADDR_INCREMENT,
DMAC_ADDR_NOCHANGE,DMAC_MSIZE_4, DMAC_TRANS_WIDTH_32, receive_buf_len + send_buf_len);
dmac_wait_done(dma_send_channel_num);
dmac_wait_done(dma_receive_channel_num);
for (i = 0; i < receive_buf_len; i++)
{
receive_buf[i] = (uint8_t)write_cmd[i];
}
free(write_cmd);
}
static int i2c_dma_irq(void *ctx)
{
i2c_instance_t *v_instance = (i2c_instance_t *)ctx;
volatile i2c_t* i2c_adapter = i2c[v_instance->i2c_num];
dmac_irq_unregister(v_instance->dmac_channel);
if(v_instance->TransferMode == I2C_SEND)
{
while ((i2c_adapter->status & I2C_STATUS_ACTIVITY) || !(i2c_adapter->status & I2C_STATUS_TFE))
{
if (i2c_adapter->tx_abrt_source != 0)
{
spinlock_unlock(&v_instance->lock);
return -1;
}
}
}
spinlock_unlock(&v_instance->lock);
if(v_instance->i2c_int_instance.callback)
{
v_instance->i2c_int_instance.callback(v_instance->i2c_int_instance.ctx);
}
return 0;
}
void i2c_handle_data_dma(i2c_device_number_t i2c_num, i2c_data_t data, plic_interrupt_t *cb)
{
configASSERT(i2c_num < I2C_MAX_NUM);
configASSERT(data.tx_channel < DMAC_CHANNEL_MAX && data.rx_channel < DMAC_CHANNEL_MAX);
spinlock_lock(&g_i2c_instance[i2c_num].lock);
if(cb)
{
g_i2c_instance[i2c_num].i2c_int_instance.callback = cb->callback;
g_i2c_instance[i2c_num].i2c_int_instance.ctx = cb->ctx;
}
volatile i2c_t* i2c_adapter = i2c[i2c_num];
if(data.TransferMode == I2C_SEND)
{
configASSERT(data.tx_buf && data.tx_len);
i2c_adapter->clr_tx_abrt = i2c_adapter->clr_tx_abrt;
if(cb)
{
g_i2c_instance[i2c_num].dmac_channel = data.tx_channel;
g_i2c_instance[i2c_num].TransferMode = I2C_SEND;
dmac_irq_register(data.tx_channel, i2c_dma_irq, &g_i2c_instance[i2c_num], cb->priority);
}
sysctl_dma_select((sysctl_dma_channel_t)data.tx_channel, SYSCTL_DMA_SELECT_I2C0_TX_REQ + i2c_num * 2);
dmac_set_single_mode(data.tx_channel, data.tx_buf, (void *)(&i2c_adapter->data_cmd), DMAC_ADDR_INCREMENT, DMAC_ADDR_NOCHANGE,
DMAC_MSIZE_4, DMAC_TRANS_WIDTH_32, data.tx_len);
if(!cb)
{
dmac_wait_done(data.tx_channel);
while ((i2c_adapter->status & I2C_STATUS_ACTIVITY) || !(i2c_adapter->status & I2C_STATUS_TFE))
{
if (i2c_adapter->tx_abrt_source != 0)
configASSERT(!"source abort");
}
}
}
else
{
configASSERT(data.rx_buf && data.rx_len);
if(data.tx_len)
configASSERT(data.tx_buf);
if(cb)
{
g_i2c_instance[i2c_num].dmac_channel = data.rx_channel;
g_i2c_instance[i2c_num].TransferMode = I2C_RECEIVE;
dmac_irq_register(data.rx_channel, i2c_dma_irq, &g_i2c_instance[i2c_num], cb->priority);
}
sysctl_dma_select((sysctl_dma_channel_t)data.rx_channel, SYSCTL_DMA_SELECT_I2C0_RX_REQ + i2c_num * 2);
dmac_set_single_mode(data.rx_channel, (void *)(&i2c_adapter->data_cmd), data.rx_buf, DMAC_ADDR_NOCHANGE,
DMAC_ADDR_INCREMENT,DMAC_MSIZE_1, DMAC_TRANS_WIDTH_32, data.rx_len);
sysctl_dma_select((sysctl_dma_channel_t)data.tx_channel, SYSCTL_DMA_SELECT_I2C0_TX_REQ + i2c_num * 2);
if(data.tx_len)
{
configASSERT(data.tx_buf);
dmac_set_single_mode(data.tx_channel, data.tx_buf, (void *)(&i2c_adapter->data_cmd), DMAC_ADDR_INCREMENT,
DMAC_ADDR_NOCHANGE,DMAC_MSIZE_4, DMAC_TRANS_WIDTH_32, data.tx_len);
dmac_wait_done(data.tx_channel);
}
static uint32_t s_read_cmd = I2C_DATA_CMD_CMD;
dmac_set_single_mode(data.tx_channel, &s_read_cmd, (void *)(&i2c_adapter->data_cmd), DMAC_ADDR_NOCHANGE,
DMAC_ADDR_NOCHANGE,DMAC_MSIZE_1, DMAC_TRANS_WIDTH_32, data.rx_len);
if(!cb)
{
dmac_wait_done(data.tx_channel);
dmac_wait_done(data.rx_channel);
}
}
if(!cb)
spinlock_unlock(&g_i2c_instance[i2c_num].lock);
}

View File

@ -0,0 +1,323 @@
/* Copyright 2018 Canaan Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* @file clint.h
* @brief add from Canaan k210 SDK
* https://canaan-creative.com/developer
* @version 1.0
* @author AIIT XUOS Lab
* @date 2021-04-25
*/
#ifndef __CLINT_H__
#define __CLINT_H__
#include <stddef.h>
#include <stdint.h>
#include "platform.h"
#ifdef __cplusplus
extern "C" {
#endif
/* clang-format off */
/* Register address offsets */
#define CLINT_MSIP (0x0000)
#define CLINT_MSIP_SIZE (0x4)
#define CLINT_MTIMECMP (0x4000)
#define CLINT_MTIMECMP_SIZE (0x8)
#define CLINT_MTIME (0xBFF8)
#define CLINT_MTIME_SIZE (0x8)
/* Max number of cores */
#define CLINT_MAX_CORES (4095)
/* Real number of cores */
#define CLINT_NUM_CORES (2)
/* Clock frequency division factor */
#define CLINT_CLOCK_DIV (50)
/* clang-format on */
/**
* @brief MSIP Registers
*
* Machine-mode software interrupts are generated by writing to a
* per-core memory-mapped control register. The msip registers are
* 32-bit wide WARL registers, where the LSB is reflected in the
* msip bit of the associated cores mip register. Other bits in
* the msip registers are hardwired to zero. The mapping supports
* up to 4095 machine-mode cores.
*/
typedef struct _clint_msip
{
uint32_t msip : 1; /*!< Bit 0 is msip */
uint32_t zero : 31; /*!< Bits [32:1] is 0 */
} __attribute__((packed, aligned(4))) clint_msip_t;
/**
* @brief Timer compare Registers Machine-mode timer interrupts are
* generated by a real-time counter and a per-core comparator. The
* mtime register is a 64-bit read-only register that contains the
* current value of the real-time counter. Each mtimecmp register
* holds its cores time comparator. A timer interrupt is pending
* whenever mtime is greater than or equal to the value in a
* cores mtimecmp register. The timer interrupt is reflected in
* the mtip bit of the associated cores mip register.
*/
typedef uint64_t clint_mtimecmp_t;
/**
* @brief Timer Registers
*
* The mtime register has a 64-bit precision on all RV32, RV64,
* and RV128 systems. Platforms provide a 64-bit memory-mapped
* machine-mode timer compare register (mtimecmp), which causes a
* timer interrupt to be posted when the mtime register contains a
* value greater than or equal to the value in the mtimecmp
* register. The interrupt remains posted until it is cleared by
* writing the mtimecmp register. The interrupt will only be taken
* if interrupts are enabled and the MTIE bit is set in the mie
* register.
*/
typedef uint64_t clint_mtime_t;
/**
* @brief CLINT object
*
* Coreplex-Local INTerrupts, which includes software interrupts,
* local timer interrupts, and other interrupts routed directly to
* a core.
*/
typedef struct _clint
{
/* 0x0000 to 0x3FF8, MSIP Registers */
clint_msip_t msip[CLINT_MAX_CORES];
/* Resverd space, do not use */
uint32_t resv0;
/* 0x4000 to 0xBFF0, Timer Compare Registers */
clint_mtimecmp_t mtimecmp[CLINT_MAX_CORES];
/* 0xBFF8, Time Register */
clint_mtime_t mtime;
} __attribute__((packed, aligned(4))) clint_t;
/**
* @brief Clint object instanse
*/
extern volatile clint_t* const clint;
/**
* @brief Definitions for the timer callbacks
*/
typedef int (*clint_timer_callback_t)(void *ctx);
/**
* @brief Definitions for local interprocessor interrupt callbacks
*/
typedef int (*clint_ipi_callback_t)(void *ctx);
typedef struct _clint_timer_instance
{
uint64_t interval;
uint64_t cycles;
uint64_t single_shot;
clint_timer_callback_t callback;
void *ctx;
} clint_timer_instance_t;
typedef struct _clint_ipi_instance
{
clint_ipi_callback_t callback;
void *ctx;
} clint_ipi_instance_t;
/**
* @brief Get the time form CLINT timer register
*
* @note The CLINT must init to get right time
*
* @return 64bit Time
*/
uint64_t clint_get_time(void);
/**
* @brief Init the CLINT timer
*
* @note MIP_MTIP will be clear after init. The MSTATUS_MIE must set by
* user.
*
* @return result
* - 0 Success
* - Other Fail
*/
int clint_timer_init(void);
/**
* @brief Stop the CLINT timer
*
* @note MIP_MTIP will be clear after stop
*
* @return result
* - 0 Success
* - Other Fail
*/
int clint_timer_stop(void);
/**
* @brief Start the CLINT timer
*
* @param[in] interval The interval with Millisecond(ms)
* @param[in] single_shot Single shot or repeat
*
* @return result
* - 0 Success
* - Other Fail
*/
int clint_timer_start(uint64_t interval, int single_shot);
/**
* @brief Get the interval of timer
*
* @return The interval with Millisecond(ms)
*/
uint64_t clint_timer_get_interval(void);
/**
* @brief Set the interval with Millisecond(ms)
*
* @param[in] interval The interval with Millisecond(ms)
*
* @return result
* - 0 Success
* - Other Fail
*/
int clint_timer_set_interval(uint64_t interval);
/**
* @brief Get whether the timer is a single shot timer
*
* @return result
* - 0 It is a repeat timer
* - 1 It is a single shot timer
*/
int clint_timer_get_single_shot(void);
/**
* @brief Set the timer working as a single shot timer or repeat timer
*
* @param[in] single_shot Single shot or repeat
*
* @return result
* - 0 Success
* - Other Fail
*/
int clint_timer_set_single_shot(int single_shot);
/**
* @brief Set user callback function when timer is timeout
*
* @param[in] callback The callback function
* @param[in] ctx The context
*
* @return result
* - 0 Success
* - Other Fail
*/
int clint_timer_register(clint_timer_callback_t callback, void *ctx);
/**
* @brief Deregister user callback function
*
* @return result
* - 0 Success
* - Other Fail
*/
int clint_timer_unregister(void);
/**
* @brief Initialize local interprocessor interrupt
*
* @return result
* - 0 Success
* - Other Fail
*/
int clint_ipi_init(void);
/**
* @brief Enable local interprocessor interrupt
*
* @return result
* - 0 Success
* - Other Fail
*/
int clint_ipi_enable(void);
/**
* @brief Disable local interprocessor interrupt
*
* @return result
* - 0 Success
* - Other Fail
*/
int clint_ipi_disable(void);
/**
* @brief Send local interprocessor interrupt to core by core id
*
* @param[in] core_id The core identifier
*
* @return result
* - 0 Success
* - Other Fail
*/
int clint_ipi_send(size_t core_id);
/**
* @brief Clear local interprocessor interrupt
*
* @param[in] core_id The core identifier
*
* @return result
* - 1 An IPI was pending
* - 0 Non IPI was pending
* - -1 Fail
*/
int clint_ipi_clear(size_t core_id);
/**
* @brief Set user callback function when interprocessor interrupt
*
* @param[in] callback The callback function
* @param[in] ctx The context
*
* @return result
* - 0 Success
* - Other Fail
*/
int clint_ipi_register(clint_ipi_callback_t callback, void *ctx);
/**
* @brief Deregister user callback function
*
* @return result
* - 0 Success
* - Other Fail
*/
int clint_ipi_unregister(void);
#ifdef __cplusplus
}
#endif
#endif /* __CLINT_H__ */

View File

@ -0,0 +1,36 @@
/*
* Copyright (c) 2020 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
/**
* @file connect_gpio.h
* @brief define kd233-board gpio function and struct
* @version 1.0
* @author AIIT XUOS Lab
* @date 2021-04-25
*/
#ifndef CONNECT_GPIO_H
#define CONNECT_GPIO_H
#include <device.h>
#ifdef __cplusplus
extern "C" {
#endif
int HwGpioInit(void);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,37 @@
/*
* Copyright (c) 2020 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
/**
* @file connect_hwtimer.h
* @brief define kd233-board hwtimer function and struct
* @version 1.0
* @author AIIT XUOS Lab
* @date 2021-04-25
*/
#ifndef CONNECT_HWTIMER_H
#define CONNECT_HWTIMER_H
#include <device.h>
#include "hardware_hwtimer.h"
#ifdef __cplusplus
extern "C" {
#endif
int HwTimerInit(void);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,36 @@
/*
* Copyright (c) 2020 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
/**
* @file connect_i2c.h
* @brief define kd233-board i2c function and struct
* @version 1.0
* @author AIIT XUOS Lab
* @date 2021-04-25
*/
#ifndef CONNECT_I2C_H
#define CONNECT_I2C_H
#include <device.h>
#ifdef __cplusplus
extern "C" {
#endif
int HwI2cInit(void);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,36 @@
/*
* Copyright (c) 2020 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
/**
* @file connect_rtc.h
* @brief define kd233-board rtc function and struct
* @version 1.0
* @author AIIT XUOS Lab
* @date 2021-04-25
*/
#ifndef CONNECT_RTC_H
#define CONNECT_RTC_H
#include <device.h>
#ifdef __cplusplus
extern "C" {
#endif
int HwRtcInit(void);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,36 @@
/*
* Copyright (c) 2020 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
/**
* @file connect_spi.h
* @brief define kd233-board spi function and struct
* @version 1.0
* @author AIIT XUOS Lab
* @date 2021-04-25
*/
#ifndef CONNECT_SPI_H
#define CONNECT_SPI_H
#include <device.h>
#ifdef __cplusplus
extern "C" {
#endif
int HwSpiInit(void);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,40 @@
/*
* Copyright (c) 2020 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
/**
* @file connect_uart.h
* @brief define kd233-board uart function and struct
* @version 1.0
* @author AIIT XUOS Lab
* @date 2021-04-25
*/
#ifndef CONNECT_UART_H
#define CONNECT_UART_H
#include <device.h>
#ifdef __cplusplus
extern "C" {
#endif
#define KERNEL_CONSOLE_BUS_NAME SERIAL_BUS_NAME_0
#define KERNEL_CONSOLE_DRV_NAME SERIAL_DRV_NAME_0
#define KERNEL_CONSOLE_DEVICE_NAME SERIAL_0_DEVICE_NAME_0
int HwUartInit(void);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,36 @@
/*
* Copyright (c) 2020 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
/**
* @file connect_wdt.h
* @brief define kd233-board wdt function and struct
* @version 1.0
* @author AIIT XUOS Lab
* @date 2021-04-25
*/
#ifndef CONNECT_WDT_H
#define CONNECT_WDT_H
#include <device.h>
#ifdef __cplusplus
extern "C" {
#endif
int HwWdtInit(void);
#ifdef __cplusplus
}
#endif
#endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,55 @@
/*
* Copyright (c) 2006-2018, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2019-03-19 ZYH first version
*/
/**
* @file drv_io_config.h
* @brief define kd233-board io configure
* @version 1.0
* @author AIIT XUOS Lab
* @date 2021-04-25
*/
/*************************************************
File name: drv_io_config.h
Description: define kd233-board io configure
Others: take RT-Thread v4.0.2/bsp/k210/driver/drv_io_config.h for references
https://github.com/RT-Thread/rt-thread/tree/v4.0.2
History:
1. Date: 2021-04-25
Author: AIIT XUOS Lab
Modification: add kd233-board io configure define
*************************************************/
#ifndef __DRV_IO_CONFIG_H__
#define __DRV_IO_CONFIG_H__
enum HS_GPIO_CONFIG
{
#ifdef BSP_USING_LCD
LCD_DC_PIN = 0, /* LCD DC PIN */
#endif
#ifdef BSP_SPI1_USING_SS0
SPI1_CS0_PIN,
#endif
#ifdef BSP_SPI1_USING_SS1
SPI1_CS1_PIN,
#endif
#ifdef BSP_SPI1_USING_SS2
SPI1_CS2_PIN,
#endif
#ifdef BSP_SPI1_USING_SS3
SPI1_CS3_PIN,
#endif
GPIO_ALLOC_START /* index of gpio driver start */
};
extern int IoConfigInit(void);
#endif

View File

@ -0,0 +1,279 @@
/* Copyright 2018 Canaan Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* @file dvp.h
* @brief add from Canaan k210 SDK
* https://canaan-creative.com/developer
* @version 1.0
* @author AIIT XUOS Lab
* @date 2021-04-25
*/
#ifndef __DVP_H__
#define __DVP_H__
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
/* clang-format off */
/**
* @brief DVP object
*/
typedef struct _dvp
{
uint32_t dvp_cfg;
uint32_t r_addr;
uint32_t g_addr;
uint32_t b_addr;
uint32_t cmos_cfg;
uint32_t sccb_cfg;
uint32_t sccb_ctl;
uint32_t axi;
uint32_t sts;
uint32_t reverse;
uint32_t rgb_addr;
} __attribute__((packed, aligned(4))) dvp_t;
/* DVP Config Register */
#define DVP_CFG_START_INT_ENABLE 0x00000001U
#define DVP_CFG_FINISH_INT_ENABLE 0x00000002U
#define DVP_CFG_AI_OUTPUT_ENABLE 0x00000004U
#define DVP_CFG_DISPLAY_OUTPUT_ENABLE 0x00000008U
#define DVP_CFG_AUTO_ENABLE 0x00000010U
#define DVP_CFG_BURST_SIZE_4BEATS 0x00000100U
#define DVP_CFG_FORMAT_MASK 0x00000600U
#define DVP_CFG_RGB_FORMAT 0x00000000U
#define DVP_CFG_YUV_FORMAT 0x00000200U
#define DVP_CFG_Y_FORMAT 0x00000600U
#define DVP_CFG_HREF_BURST_NUM_MASK 0x000FF000U
#define DVP_CFG_HREF_BURST_NUM(x) ((x) << 12)
#define DVP_CFG_LINE_NUM_MASK 0x3FF00000U
#define DVP_CFG_LINE_NUM(x) ((x) << 20)
/* DVP CMOS Config Register */
#define DVP_CMOS_CLK_DIV_MASK 0x000000FFU
#define DVP_CMOS_CLK_DIV(x) ((x) << 0)
#define DVP_CMOS_CLK_ENABLE 0x00000100U
#define DVP_CMOS_RESET 0x00010000U
#define DVP_CMOS_POWER_DOWN 0x01000000U
/* DVP SCCB Config Register */
#define DVP_SCCB_BYTE_NUM_MASK 0x00000003U
#define DVP_SCCB_BYTE_NUM_2 0x00000001U
#define DVP_SCCB_BYTE_NUM_3 0x00000002U
#define DVP_SCCB_BYTE_NUM_4 0x00000003U
#define DVP_SCCB_SCL_LCNT_MASK 0x0000FF00U
#define DVP_SCCB_SCL_LCNT(x) ((x) << 8)
#define DVP_SCCB_SCL_HCNT_MASK 0x00FF0000U
#define DVP_SCCB_SCL_HCNT(x) ((x) << 16)
#define DVP_SCCB_RDATA_BYTE(x) ((x) >> 24)
/* DVP SCCB Control Register */
#define DVP_SCCB_WRITE_DATA_ENABLE 0x00000001U
#define DVP_SCCB_DEVICE_ADDRESS(x) ((x) << 0)
#define DVP_SCCB_REG_ADDRESS(x) ((x) << 8)
#define DVP_SCCB_WDATA_BYTE0(x) ((x) << 16)
#define DVP_SCCB_WDATA_BYTE1(x) ((x) << 24)
/* DVP AXI Register */
#define DVP_AXI_GM_MLEN_MASK 0x000000FFU
#define DVP_AXI_GM_MLEN_1BYTE 0x00000000U
#define DVP_AXI_GM_MLEN_4BYTE 0x00000003U
/* DVP STS Register */
#define DVP_STS_FRAME_START 0x00000001U
#define DVP_STS_FRAME_START_WE 0x00000002U
#define DVP_STS_FRAME_FINISH 0x00000100U
#define DVP_STS_FRAME_FINISH_WE 0x00000200U
#define DVP_STS_DVP_EN 0x00010000U
#define DVP_STS_DVP_EN_WE 0x00020000U
#define DVP_STS_SCCB_EN 0x01000000U
#define DVP_STS_SCCB_EN_WE 0x02000000U
/* clang-format on */
typedef enum _dvp_output_mode
{
DVP_OUTPUT_AI,
DVP_OUTPUT_DISPLAY,
} dvp_output_mode_t;
/**
* @brief DVP object instance
*/
extern volatile dvp_t* const dvp;
/**
* @brief Initialize DVP
*/
void dvp_init(uint8_t reg_len);
/**
* @brief Set image format
*
* @param[in] format The image format
*/
void dvp_set_image_format(uint32_t format);
/**
* @brief Set image size
*
* @param[in] width The width of image
* @param[in] height The height of image
*/
void dvp_set_image_size(uint32_t width, uint32_t height);
/**
* @brief Set the address of RGB for AI
*
* @param[in] r_addr The R address of RGB
* @param[in] g_addr The G address of RGB
* @param[in] b_addr The B address of RGB
*/
void dvp_set_ai_addr(uint32_t r_addr, uint32_t g_addr, uint32_t b_addr);
/**
* @brief Set the address of RGB for display
*
* @param[in] r_addr The R address of RGB
* @param[in] g_addr The G address of RGB
* @param[in] b_addr The B address of RGB
*/
void dvp_set_display_addr(uint32_t addr);
/**
* @brief The frame start transfer
*/
void dvp_start_frame(void);
/**
* @brief The DVP convert start
*/
void dvp_start_convert(void);
/**
* @brief The DVP convert finish
*/
void dvp_finish_convert(void);
/**
* @brief Get the image data
*
* @note The image data stored in the address of RGB
*/
void dvp_get_image(void);
/**
* @brief Use SCCB write register
*
* @param[in] DevAddr The device address
* @param[in] reg_addr The register address
* @param[in] reg_data The register data
*/
void dvp_sccb_send_data(uint8_t DevAddr, uint16_t reg_addr, uint8_t reg_data);
/**
* @brief Use SCCB read register
*
* @param[in] DevAddr The device address
* @param[in] reg_addr The register address
*
* @return The register value
*/
uint8_t dvp_sccb_receive_data(uint8_t DevAddr, uint16_t reg_addr);
/**
* @brief Enable dvp burst
*/
void dvp_enable_burst(void);
/**
* @brief Disable dvp burst
*/
void dvp_disable_burst(void);
/**
* @brief Enable or disable dvp interrupt
*
* @param[in] interrupt Dvp interrupt
* @param[in] status 0:disable 1:enable
*
*/
void dvp_config_interrupt(uint32_t interrupt, uint8_t enable);
/**
* @brief Get dvp interrupt status
*
* @param[in] interrupt Dvp interrupt
*
*
* @return Interrupt status
* - 0 false
* - 1 true
*/
int dvp_get_interrupt(uint32_t interrupt);
/**
* @brief Clear dvp interrupt status
*
* @param[in] interrupt Dvp interrupt
*
*/
void dvp_clear_interrupt(uint32_t interrupt);
/**
* @brief Enable dvp auto mode
*/
void dvp_enable_auto(void);
/**
* @brief Disable dvp auto mode
*/
void dvp_disable_auto(void);
/**
* @brief Dvp ouput data enable or not
*
* @param[in] index 0:AI, 1:display
* @param[in] enable 0:disable, 1:enable
*
*/
void dvp_set_output_enable(dvp_output_mode_t index, int enable);
/**
* @brief Set sccb clock rate
*
* @param[in] clk_rate Sccb clock rate
*
* @return The real sccb clock rate
*/
uint32_t dvp_sccb_set_clk_rate(uint32_t clk_rate);
/**
* @brief Set xclk rate
*
* @param[in] clk_rate xclk rate
*
* @return The real xclk rate
*/
uint32_t dvp_set_xclk_rate(uint32_t xclk_rate);
#ifdef __cplusplus
}
#endif
#endif /* __DVP_H__ */

View File

@ -0,0 +1,425 @@
/* Copyright 2018 Canaan Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* @file font.h
* @brief add from Canaan k210 SDK
* https://canaan-creative.com/developer
* @version 1.0
* @author AIIT XUOS Lab
* @date 2021-04-25
*/
#ifndef __FONT_H__
#define __FONT_H__
//ASCII char table
//offset 32
//ASCII char : !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~
//bytes of a single char : (size/8+((size%8)?1:0))*(size/2), size : (12/16/24/32...) code table size
//12*12 ASCII code
const unsigned char asc2_1206[95][12]={
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*" ",0*/
{0x00,0x00,0x00,0x00,0x3F,0x40,0x00,0x00,0x00,0x00,0x00,0x00},/*"!",1*/
{0x00,0x00,0x30,0x00,0x40,0x00,0x30,0x00,0x40,0x00,0x00,0x00},/*""",2*/
{0x09,0x00,0x0B,0xC0,0x3D,0x00,0x0B,0xC0,0x3D,0x00,0x09,0x00},/*"#",3*/
{0x18,0xC0,0x24,0x40,0x7F,0xE0,0x22,0x40,0x31,0x80,0x00,0x00},/*"$",4*/
{0x18,0x00,0x24,0xC0,0x1B,0x00,0x0D,0x80,0x32,0x40,0x01,0x80},/*"%",5*/
{0x03,0x80,0x1C,0x40,0x27,0x40,0x1C,0x80,0x07,0x40,0x00,0x40},/*"&",6*/
{0x10,0x00,0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"'",7*/
{0x00,0x00,0x00,0x00,0x00,0x00,0x1F,0x80,0x20,0x40,0x40,0x20},/*"(",8*/
{0x00,0x00,0x40,0x20,0x20,0x40,0x1F,0x80,0x00,0x00,0x00,0x00},/*")",9*/
{0x09,0x00,0x06,0x00,0x1F,0x80,0x06,0x00,0x09,0x00,0x00,0x00},/*"*",10*/
{0x04,0x00,0x04,0x00,0x3F,0x80,0x04,0x00,0x04,0x00,0x00,0x00},/*"+",11*/
{0x00,0x10,0x00,0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*",",12*/
{0x04,0x00,0x04,0x00,0x04,0x00,0x04,0x00,0x04,0x00,0x00,0x00},/*"-",13*/
{0x00,0x00,0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*".",14*/
{0x00,0x20,0x01,0xC0,0x06,0x00,0x38,0x00,0x40,0x00,0x00,0x00},/*"/",15*/
{0x1F,0x80,0x20,0x40,0x20,0x40,0x20,0x40,0x1F,0x80,0x00,0x00},/*"0",16*/
{0x00,0x00,0x10,0x40,0x3F,0xC0,0x00,0x40,0x00,0x00,0x00,0x00},/*"1",17*/
{0x18,0xC0,0x21,0x40,0x22,0x40,0x24,0x40,0x18,0x40,0x00,0x00},/*"2",18*/
{0x10,0x80,0x20,0x40,0x24,0x40,0x24,0x40,0x1B,0x80,0x00,0x00},/*"3",19*/
{0x02,0x00,0x0D,0x00,0x11,0x00,0x3F,0xC0,0x01,0x40,0x00,0x00},/*"4",20*/
{0x3C,0x80,0x24,0x40,0x24,0x40,0x24,0x40,0x23,0x80,0x00,0x00},/*"5",21*/
{0x1F,0x80,0x24,0x40,0x24,0x40,0x34,0x40,0x03,0x80,0x00,0x00},/*"6",22*/
{0x30,0x00,0x20,0x00,0x27,0xC0,0x38,0x00,0x20,0x00,0x00,0x00},/*"7",23*/
{0x1B,0x80,0x24,0x40,0x24,0x40,0x24,0x40,0x1B,0x80,0x00,0x00},/*"8",24*/
{0x1C,0x00,0x22,0xC0,0x22,0x40,0x22,0x40,0x1F,0x80,0x00,0x00},/*"9",25*/
{0x00,0x00,0x00,0x00,0x08,0x40,0x00,0x00,0x00,0x00,0x00,0x00},/*":",26*/
{0x00,0x00,0x00,0x00,0x04,0x60,0x00,0x00,0x00,0x00,0x00,0x00},/*";",27*/
{0x00,0x00,0x04,0x00,0x0A,0x00,0x11,0x00,0x20,0x80,0x40,0x40},/*"<",28*/
{0x09,0x00,0x09,0x00,0x09,0x00,0x09,0x00,0x09,0x00,0x00,0x00},/*"=",29*/
{0x00,0x00,0x40,0x40,0x20,0x80,0x11,0x00,0x0A,0x00,0x04,0x00},/*">",30*/
{0x18,0x00,0x20,0x00,0x23,0x40,0x24,0x00,0x18,0x00,0x00,0x00},/*"?",31*/
{0x1F,0x80,0x20,0x40,0x27,0x40,0x29,0x40,0x1F,0x40,0x00,0x00},/*"@",32*/
{0x00,0x40,0x07,0xC0,0x39,0x00,0x0F,0x00,0x01,0xC0,0x00,0x40},/*"A",33*/
{0x20,0x40,0x3F,0xC0,0x24,0x40,0x24,0x40,0x1B,0x80,0x00,0x00},/*"B",34*/
{0x1F,0x80,0x20,0x40,0x20,0x40,0x20,0x40,0x30,0x80,0x00,0x00},/*"C",35*/
{0x20,0x40,0x3F,0xC0,0x20,0x40,0x20,0x40,0x1F,0x80,0x00,0x00},/*"D",36*/
{0x20,0x40,0x3F,0xC0,0x24,0x40,0x2E,0x40,0x30,0xC0,0x00,0x00},/*"E",37*/
{0x20,0x40,0x3F,0xC0,0x24,0x40,0x2E,0x00,0x30,0x00,0x00,0x00},/*"F",38*/
{0x0F,0x00,0x10,0x80,0x20,0x40,0x22,0x40,0x33,0x80,0x02,0x00},/*"G",39*/
{0x20,0x40,0x3F,0xC0,0x04,0x00,0x04,0x00,0x3F,0xC0,0x20,0x40},/*"H",40*/
{0x20,0x40,0x20,0x40,0x3F,0xC0,0x20,0x40,0x20,0x40,0x00,0x00},/*"I",41*/
{0x00,0x60,0x20,0x20,0x20,0x20,0x3F,0xC0,0x20,0x00,0x20,0x00},/*"J",42*/
{0x20,0x40,0x3F,0xC0,0x24,0x40,0x0B,0x00,0x30,0xC0,0x20,0x40},/*"K",43*/
{0x20,0x40,0x3F,0xC0,0x20,0x40,0x00,0x40,0x00,0x40,0x00,0xC0},/*"L",44*/
{0x3F,0xC0,0x3C,0x00,0x03,0xC0,0x3C,0x00,0x3F,0xC0,0x00,0x00},/*"M",45*/
{0x20,0x40,0x3F,0xC0,0x0C,0x40,0x23,0x00,0x3F,0xC0,0x20,0x00},/*"N",46*/
{0x1F,0x80,0x20,0x40,0x20,0x40,0x20,0x40,0x1F,0x80,0x00,0x00},/*"O",47*/
{0x20,0x40,0x3F,0xC0,0x24,0x40,0x24,0x00,0x18,0x00,0x00,0x00},/*"P",48*/
{0x1F,0x80,0x21,0x40,0x21,0x40,0x20,0xE0,0x1F,0xA0,0x00,0x00},/*"Q",49*/
{0x20,0x40,0x3F,0xC0,0x24,0x40,0x26,0x00,0x19,0xC0,0x00,0x40},/*"R",50*/
{0x18,0xC0,0x24,0x40,0x24,0x40,0x22,0x40,0x31,0x80,0x00,0x00},/*"S",51*/
{0x30,0x00,0x20,0x40,0x3F,0xC0,0x20,0x40,0x30,0x00,0x00,0x00},/*"T",52*/
{0x20,0x00,0x3F,0x80,0x00,0x40,0x00,0x40,0x3F,0x80,0x20,0x00},/*"U",53*/
{0x20,0x00,0x3E,0x00,0x01,0xC0,0x07,0x00,0x38,0x00,0x20,0x00},/*"V",54*/
{0x38,0x00,0x07,0xC0,0x3C,0x00,0x07,0xC0,0x38,0x00,0x00,0x00},/*"W",55*/
{0x20,0x40,0x39,0xC0,0x06,0x00,0x39,0xC0,0x20,0x40,0x00,0x00},/*"X",56*/
{0x20,0x00,0x38,0x40,0x07,0xC0,0x38,0x40,0x20,0x00,0x00,0x00},/*"Y",57*/
{0x30,0x40,0x21,0xC0,0x26,0x40,0x38,0x40,0x20,0xC0,0x00,0x00},/*"Z",58*/
{0x00,0x00,0x00,0x00,0x7F,0xE0,0x40,0x20,0x40,0x20,0x00,0x00},/*"[",59*/
{0x00,0x00,0x70,0x00,0x0C,0x00,0x03,0x80,0x00,0x40,0x00,0x00},/*"\",60*/
{0x00,0x00,0x40,0x20,0x40,0x20,0x7F,0xE0,0x00,0x00,0x00,0x00},/*"]",61*/
{0x00,0x00,0x20,0x00,0x40,0x00,0x20,0x00,0x00,0x00,0x00,0x00},/*"^",62*/
{0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x10},/*"_",63*/
{0x00,0x00,0x00,0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"`",64*/
{0x00,0x00,0x02,0x80,0x05,0x40,0x05,0x40,0x03,0xC0,0x00,0x40},/*"a",65*/
{0x20,0x00,0x3F,0xC0,0x04,0x40,0x04,0x40,0x03,0x80,0x00,0x00},/*"b",66*/
{0x00,0x00,0x03,0x80,0x04,0x40,0x04,0x40,0x06,0x40,0x00,0x00},/*"c",67*/
{0x00,0x00,0x03,0x80,0x04,0x40,0x24,0x40,0x3F,0xC0,0x00,0x40},/*"d",68*/
{0x00,0x00,0x03,0x80,0x05,0x40,0x05,0x40,0x03,0x40,0x00,0x00},/*"e",69*/
{0x00,0x00,0x04,0x40,0x1F,0xC0,0x24,0x40,0x24,0x40,0x20,0x00},/*"f",70*/
{0x00,0x00,0x02,0xE0,0x05,0x50,0x05,0x50,0x06,0x50,0x04,0x20},/*"g",71*/
{0x20,0x40,0x3F,0xC0,0x04,0x40,0x04,0x00,0x03,0xC0,0x00,0x40},/*"h",72*/
{0x00,0x00,0x04,0x40,0x27,0xC0,0x00,0x40,0x00,0x00,0x00,0x00},/*"i",73*/
{0x00,0x10,0x00,0x10,0x04,0x10,0x27,0xE0,0x00,0x00,0x00,0x00},/*"j",74*/
{0x20,0x40,0x3F,0xC0,0x01,0x40,0x07,0x00,0x04,0xC0,0x04,0x40},/*"k",75*/
{0x20,0x40,0x20,0x40,0x3F,0xC0,0x00,0x40,0x00,0x40,0x00,0x00},/*"l",76*/
{0x07,0xC0,0x04,0x00,0x07,0xC0,0x04,0x00,0x03,0xC0,0x00,0x00},/*"m",77*/
{0x04,0x40,0x07,0xC0,0x04,0x40,0x04,0x00,0x03,0xC0,0x00,0x40},/*"n",78*/
{0x00,0x00,0x03,0x80,0x04,0x40,0x04,0x40,0x03,0x80,0x00,0x00},/*"o",79*/
{0x04,0x10,0x07,0xF0,0x04,0x50,0x04,0x40,0x03,0x80,0x00,0x00},/*"p",80*/
{0x00,0x00,0x03,0x80,0x04,0x40,0x04,0x50,0x07,0xF0,0x00,0x10},/*"q",81*/
{0x04,0x40,0x07,0xC0,0x02,0x40,0x04,0x00,0x04,0x00,0x00,0x00},/*"r",82*/
{0x00,0x00,0x06,0x40,0x05,0x40,0x05,0x40,0x04,0xC0,0x00,0x00},/*"s",83*/
{0x00,0x00,0x04,0x00,0x1F,0x80,0x04,0x40,0x00,0x40,0x00,0x00},/*"t",84*/
{0x04,0x00,0x07,0x80,0x00,0x40,0x04,0x40,0x07,0xC0,0x00,0x40},/*"u",85*/
{0x04,0x00,0x07,0x00,0x04,0xC0,0x01,0x80,0x06,0x00,0x04,0x00},/*"v",86*/
{0x06,0x00,0x01,0xC0,0x07,0x00,0x01,0xC0,0x06,0x00,0x00,0x00},/*"w",87*/
{0x04,0x40,0x06,0xC0,0x01,0x00,0x06,0xC0,0x04,0x40,0x00,0x00},/*"x",88*/
{0x04,0x10,0x07,0x10,0x04,0xE0,0x01,0x80,0x06,0x00,0x04,0x00},/*"y",89*/
{0x00,0x00,0x04,0x40,0x05,0xC0,0x06,0x40,0x04,0x40,0x00,0x00},/*"z",90*/
{0x00,0x00,0x00,0x00,0x04,0x00,0x7B,0xE0,0x40,0x20,0x00,0x00},/*"{",91*/
{0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xF0,0x00,0x00,0x00,0x00},/*"|",92*/
{0x00,0x00,0x40,0x20,0x7B,0xE0,0x04,0x00,0x00,0x00,0x00,0x00},/*"}",93*/
{0x40,0x00,0x80,0x00,0x40,0x00,0x20,0x00,0x20,0x00,0x40,0x00},/*"~",94*/
};
//16*16 ASCII鐎涙顑侀梿鍡欏仯闂冿拷
const unsigned char asc2_1608[95][16]={
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*" ",0*/
{0x00,0x00,0x00,0x00,0x00,0x00,0x1F,0xCC,0x00,0x0C,0x00,0x00,0x00,0x00,0x00,0x00},/*"!",1*/
{0x00,0x00,0x08,0x00,0x30,0x00,0x60,0x00,0x08,0x00,0x30,0x00,0x60,0x00,0x00,0x00},/*""",2*/
{0x02,0x20,0x03,0xFC,0x1E,0x20,0x02,0x20,0x03,0xFC,0x1E,0x20,0x02,0x20,0x00,0x00},/*"#",3*/
{0x00,0x00,0x0E,0x18,0x11,0x04,0x3F,0xFF,0x10,0x84,0x0C,0x78,0x00,0x00,0x00,0x00},/*"$",4*/
{0x0F,0x00,0x10,0x84,0x0F,0x38,0x00,0xC0,0x07,0x78,0x18,0x84,0x00,0x78,0x00,0x00},/*"%",5*/
{0x00,0x78,0x0F,0x84,0x10,0xC4,0x11,0x24,0x0E,0x98,0x00,0xE4,0x00,0x84,0x00,0x08},/*"&",6*/
{0x08,0x00,0x68,0x00,0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"'",7*/
{0x00,0x00,0x00,0x00,0x00,0x00,0x07,0xE0,0x18,0x18,0x20,0x04,0x40,0x02,0x00,0x00},/*"(",8*/
{0x00,0x00,0x40,0x02,0x20,0x04,0x18,0x18,0x07,0xE0,0x00,0x00,0x00,0x00,0x00,0x00},/*")",9*/
{0x02,0x40,0x02,0x40,0x01,0x80,0x0F,0xF0,0x01,0x80,0x02,0x40,0x02,0x40,0x00,0x00},/*"*",10*/
{0x00,0x80,0x00,0x80,0x00,0x80,0x0F,0xF8,0x00,0x80,0x00,0x80,0x00,0x80,0x00,0x00},/*"+",11*/
{0x00,0x01,0x00,0x0D,0x00,0x0E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*",",12*/
{0x00,0x00,0x00,0x80,0x00,0x80,0x00,0x80,0x00,0x80,0x00,0x80,0x00,0x80,0x00,0x80},/*"-",13*/
{0x00,0x00,0x00,0x0C,0x00,0x0C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*".",14*/
{0x00,0x00,0x00,0x06,0x00,0x18,0x00,0x60,0x01,0x80,0x06,0x00,0x18,0x00,0x20,0x00},/*"/",15*/
{0x00,0x00,0x07,0xF0,0x08,0x08,0x10,0x04,0x10,0x04,0x08,0x08,0x07,0xF0,0x00,0x00},/*"0",16*/
{0x00,0x00,0x08,0x04,0x08,0x04,0x1F,0xFC,0x00,0x04,0x00,0x04,0x00,0x00,0x00,0x00},/*"1",17*/
{0x00,0x00,0x0E,0x0C,0x10,0x14,0x10,0x24,0x10,0x44,0x11,0x84,0x0E,0x0C,0x00,0x00},/*"2",18*/
{0x00,0x00,0x0C,0x18,0x10,0x04,0x11,0x04,0x11,0x04,0x12,0x88,0x0C,0x70,0x00,0x00},/*"3",19*/
{0x00,0x00,0x00,0xE0,0x03,0x20,0x04,0x24,0x08,0x24,0x1F,0xFC,0x00,0x24,0x00,0x00},/*"4",20*/
{0x00,0x00,0x1F,0x98,0x10,0x84,0x11,0x04,0x11,0x04,0x10,0x88,0x10,0x70,0x00,0x00},/*"5",21*/
{0x00,0x00,0x07,0xF0,0x08,0x88,0x11,0x04,0x11,0x04,0x18,0x88,0x00,0x70,0x00,0x00},/*"6",22*/
{0x00,0x00,0x1C,0x00,0x10,0x00,0x10,0xFC,0x13,0x00,0x1C,0x00,0x10,0x00,0x00,0x00},/*"7",23*/
{0x00,0x00,0x0E,0x38,0x11,0x44,0x10,0x84,0x10,0x84,0x11,0x44,0x0E,0x38,0x00,0x00},/*"8",24*/
{0x00,0x00,0x07,0x00,0x08,0x8C,0x10,0x44,0x10,0x44,0x08,0x88,0x07,0xF0,0x00,0x00},/*"9",25*/
{0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x0C,0x03,0x0C,0x00,0x00,0x00,0x00,0x00,0x00},/*":",26*/
{0x00,0x00,0x00,0x00,0x00,0x01,0x01,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*";",27*/
{0x00,0x00,0x00,0x80,0x01,0x40,0x02,0x20,0x04,0x10,0x08,0x08,0x10,0x04,0x00,0x00},/*"<",28*/
{0x02,0x20,0x02,0x20,0x02,0x20,0x02,0x20,0x02,0x20,0x02,0x20,0x02,0x20,0x00,0x00},/*"=",29*/
{0x00,0x00,0x10,0x04,0x08,0x08,0x04,0x10,0x02,0x20,0x01,0x40,0x00,0x80,0x00,0x00},/*">",30*/
{0x00,0x00,0x0E,0x00,0x12,0x00,0x10,0x0C,0x10,0x6C,0x10,0x80,0x0F,0x00,0x00,0x00},/*"?",31*/
{0x03,0xE0,0x0C,0x18,0x13,0xE4,0x14,0x24,0x17,0xC4,0x08,0x28,0x07,0xD0,0x00,0x00},/*"@",32*/
{0x00,0x04,0x00,0x3C,0x03,0xC4,0x1C,0x40,0x07,0x40,0x00,0xE4,0x00,0x1C,0x00,0x04},/*"A",33*/
{0x10,0x04,0x1F,0xFC,0x11,0x04,0x11,0x04,0x11,0x04,0x0E,0x88,0x00,0x70,0x00,0x00},/*"B",34*/
{0x03,0xE0,0x0C,0x18,0x10,0x04,0x10,0x04,0x10,0x04,0x10,0x08,0x1C,0x10,0x00,0x00},/*"C",35*/
{0x10,0x04,0x1F,0xFC,0x10,0x04,0x10,0x04,0x10,0x04,0x08,0x08,0x07,0xF0,0x00,0x00},/*"D",36*/
{0x10,0x04,0x1F,0xFC,0x11,0x04,0x11,0x04,0x17,0xC4,0x10,0x04,0x08,0x18,0x00,0x00},/*"E",37*/
{0x10,0x04,0x1F,0xFC,0x11,0x04,0x11,0x00,0x17,0xC0,0x10,0x00,0x08,0x00,0x00,0x00},/*"F",38*/
{0x03,0xE0,0x0C,0x18,0x10,0x04,0x10,0x04,0x10,0x44,0x1C,0x78,0x00,0x40,0x00,0x00},/*"G",39*/
{0x10,0x04,0x1F,0xFC,0x10,0x84,0x00,0x80,0x00,0x80,0x10,0x84,0x1F,0xFC,0x10,0x04},/*"H",40*/
{0x00,0x00,0x10,0x04,0x10,0x04,0x1F,0xFC,0x10,0x04,0x10,0x04,0x00,0x00,0x00,0x00},/*"I",41*/
{0x00,0x03,0x00,0x01,0x10,0x01,0x10,0x01,0x1F,0xFE,0x10,0x00,0x10,0x00,0x00,0x00},/*"J",42*/
{0x10,0x04,0x1F,0xFC,0x11,0x04,0x03,0x80,0x14,0x64,0x18,0x1C,0x10,0x04,0x00,0x00},/*"K",43*/
{0x10,0x04,0x1F,0xFC,0x10,0x04,0x00,0x04,0x00,0x04,0x00,0x04,0x00,0x0C,0x00,0x00},/*"L",44*/
{0x10,0x04,0x1F,0xFC,0x1F,0x00,0x00,0xFC,0x1F,0x00,0x1F,0xFC,0x10,0x04,0x00,0x00},/*"M",45*/
{0x10,0x04,0x1F,0xFC,0x0C,0x04,0x03,0x00,0x00,0xE0,0x10,0x18,0x1F,0xFC,0x10,0x00},/*"N",46*/
{0x07,0xF0,0x08,0x08,0x10,0x04,0x10,0x04,0x10,0x04,0x08,0x08,0x07,0xF0,0x00,0x00},/*"O",47*/
{0x10,0x04,0x1F,0xFC,0x10,0x84,0x10,0x80,0x10,0x80,0x10,0x80,0x0F,0x00,0x00,0x00},/*"P",48*/
{0x07,0xF0,0x08,0x18,0x10,0x24,0x10,0x24,0x10,0x1C,0x08,0x0A,0x07,0xF2,0x00,0x00},/*"Q",49*/
{0x10,0x04,0x1F,0xFC,0x11,0x04,0x11,0x00,0x11,0xC0,0x11,0x30,0x0E,0x0C,0x00,0x04},/*"R",50*/
{0x00,0x00,0x0E,0x1C,0x11,0x04,0x10,0x84,0x10,0x84,0x10,0x44,0x1C,0x38,0x00,0x00},/*"S",51*/
{0x18,0x00,0x10,0x00,0x10,0x04,0x1F,0xFC,0x10,0x04,0x10,0x00,0x18,0x00,0x00,0x00},/*"T",52*/
{0x10,0x00,0x1F,0xF8,0x10,0x04,0x00,0x04,0x00,0x04,0x10,0x04,0x1F,0xF8,0x10,0x00},/*"U",53*/
{0x10,0x00,0x1E,0x00,0x11,0xE0,0x00,0x1C,0x00,0x70,0x13,0x80,0x1C,0x00,0x10,0x00},/*"V",54*/
{0x1F,0xC0,0x10,0x3C,0x00,0xE0,0x1F,0x00,0x00,0xE0,0x10,0x3C,0x1F,0xC0,0x00,0x00},/*"W",55*/
{0x10,0x04,0x18,0x0C,0x16,0x34,0x01,0xC0,0x01,0xC0,0x16,0x34,0x18,0x0C,0x10,0x04},/*"X",56*/
{0x10,0x00,0x1C,0x00,0x13,0x04,0x00,0xFC,0x13,0x04,0x1C,0x00,0x10,0x00,0x00,0x00},/*"Y",57*/
{0x08,0x04,0x10,0x1C,0x10,0x64,0x10,0x84,0x13,0x04,0x1C,0x04,0x10,0x18,0x00,0x00},/*"Z",58*/
{0x00,0x00,0x00,0x00,0x00,0x00,0x7F,0xFE,0x40,0x02,0x40,0x02,0x40,0x02,0x00,0x00},/*"[",59*/
{0x00,0x00,0x30,0x00,0x0C,0x00,0x03,0x80,0x00,0x60,0x00,0x1C,0x00,0x03,0x00,0x00},/*"\",60*/
{0x00,0x00,0x40,0x02,0x40,0x02,0x40,0x02,0x7F,0xFE,0x00,0x00,0x00,0x00,0x00,0x00},/*"]",61*/
{0x00,0x00,0x00,0x00,0x20,0x00,0x40,0x00,0x40,0x00,0x40,0x00,0x20,0x00,0x00,0x00},/*"^",62*/
{0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01},/*"_",63*/
{0x00,0x00,0x40,0x00,0x40,0x00,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"`",64*/
{0x00,0x00,0x00,0x98,0x01,0x24,0x01,0x44,0x01,0x44,0x01,0x44,0x00,0xFC,0x00,0x04},/*"a",65*/
{0x10,0x00,0x1F,0xFC,0x00,0x88,0x01,0x04,0x01,0x04,0x00,0x88,0x00,0x70,0x00,0x00},/*"b",66*/
{0x00,0x00,0x00,0x70,0x00,0x88,0x01,0x04,0x01,0x04,0x01,0x04,0x00,0x88,0x00,0x00},/*"c",67*/
{0x00,0x00,0x00,0x70,0x00,0x88,0x01,0x04,0x01,0x04,0x11,0x08,0x1F,0xFC,0x00,0x04},/*"d",68*/
{0x00,0x00,0x00,0xF8,0x01,0x44,0x01,0x44,0x01,0x44,0x01,0x44,0x00,0xC8,0x00,0x00},/*"e",69*/
{0x00,0x00,0x01,0x04,0x01,0x04,0x0F,0xFC,0x11,0x04,0x11,0x04,0x11,0x00,0x18,0x00},/*"f",70*/
{0x00,0x00,0x00,0xD6,0x01,0x29,0x01,0x29,0x01,0x29,0x01,0xC9,0x01,0x06,0x00,0x00},/*"g",71*/
{0x10,0x04,0x1F,0xFC,0x00,0x84,0x01,0x00,0x01,0x00,0x01,0x04,0x00,0xFC,0x00,0x04},/*"h",72*/
{0x00,0x00,0x01,0x04,0x19,0x04,0x19,0xFC,0x00,0x04,0x00,0x04,0x00,0x00,0x00,0x00},/*"i",73*/
{0x00,0x00,0x00,0x03,0x00,0x01,0x01,0x01,0x19,0x01,0x19,0xFE,0x00,0x00,0x00,0x00},/*"j",74*/
{0x10,0x04,0x1F,0xFC,0x00,0x24,0x00,0x40,0x01,0xB4,0x01,0x0C,0x01,0x04,0x00,0x00},/*"k",75*/
{0x00,0x00,0x10,0x04,0x10,0x04,0x1F,0xFC,0x00,0x04,0x00,0x04,0x00,0x00,0x00,0x00},/*"l",76*/
{0x01,0x04,0x01,0xFC,0x01,0x04,0x01,0x00,0x01,0xFC,0x01,0x04,0x01,0x00,0x00,0xFC},/*"m",77*/
{0x01,0x04,0x01,0xFC,0x00,0x84,0x01,0x00,0x01,0x00,0x01,0x04,0x00,0xFC,0x00,0x04},/*"n",78*/
{0x00,0x00,0x00,0xF8,0x01,0x04,0x01,0x04,0x01,0x04,0x01,0x04,0x00,0xF8,0x00,0x00},/*"o",79*/
{0x01,0x01,0x01,0xFF,0x00,0x85,0x01,0x04,0x01,0x04,0x00,0x88,0x00,0x70,0x00,0x00},/*"p",80*/
{0x00,0x00,0x00,0x70,0x00,0x88,0x01,0x04,0x01,0x04,0x01,0x05,0x01,0xFF,0x00,0x01},/*"q",81*/
{0x01,0x04,0x01,0x04,0x01,0xFC,0x00,0x84,0x01,0x04,0x01,0x00,0x01,0x80,0x00,0x00},/*"r",82*/
{0x00,0x00,0x00,0xCC,0x01,0x24,0x01,0x24,0x01,0x24,0x01,0x24,0x01,0x98,0x00,0x00},/*"s",83*/
{0x00,0x00,0x01,0x00,0x01,0x00,0x07,0xF8,0x01,0x04,0x01,0x04,0x00,0x00,0x00,0x00},/*"t",84*/
{0x01,0x00,0x01,0xF8,0x00,0x04,0x00,0x04,0x00,0x04,0x01,0x08,0x01,0xFC,0x00,0x04},/*"u",85*/
{0x01,0x00,0x01,0x80,0x01,0x70,0x00,0x0C,0x00,0x10,0x01,0x60,0x01,0x80,0x01,0x00},/*"v",86*/
{0x01,0xF0,0x01,0x0C,0x00,0x30,0x01,0xC0,0x00,0x30,0x01,0x0C,0x01,0xF0,0x01,0x00},/*"w",87*/
{0x00,0x00,0x01,0x04,0x01,0x8C,0x00,0x74,0x01,0x70,0x01,0x8C,0x01,0x04,0x00,0x00},/*"x",88*/
{0x01,0x01,0x01,0x81,0x01,0x71,0x00,0x0E,0x00,0x18,0x01,0x60,0x01,0x80,0x01,0x00},/*"y",89*/
{0x00,0x00,0x01,0x84,0x01,0x0C,0x01,0x34,0x01,0x44,0x01,0x84,0x01,0x0C,0x00,0x00},/*"z",90*/
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x3E,0xFC,0x40,0x02,0x40,0x02},/*"{",91*/
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00},/*"|",92*/
{0x00,0x00,0x40,0x02,0x40,0x02,0x3E,0xFC,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"}",93*/
{0x00,0x00,0x60,0x00,0x80,0x00,0x80,0x00,0x40,0x00,0x40,0x00,0x20,0x00,0x20,0x00},/*"~",94*/
};
//24*24 ASCII code
const unsigned char asc2_2412[95][36]={
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*" ",0*/
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0x80,0x38,0x0F,0xFE,0x38,0x0F,0x80,0x38,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"!",1*/
{0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x06,0x00,0x00,0x0C,0x00,0x00,0x38,0x00,0x00,0x31,0x00,0x00,0x06,0x00,0x00,0x0C,0x00,0x00,0x38,0x00,0x00,0x30,0x00,0x00,0x00,0x00,0x00},/*""",2*/
{0x00,0x00,0x00,0x00,0x61,0x80,0x00,0x67,0xF8,0x07,0xF9,0x80,0x00,0x61,0x80,0x00,0x61,0x80,0x00,0x61,0x80,0x00,0x61,0x80,0x00,0x67,0xF8,0x07,0xF9,0x80,0x00,0x61,0x80,0x00,0x00,0x00},/*"#",3*/
{0x00,0x00,0x00,0x00,0x00,0x00,0x01,0xC0,0xE0,0x03,0xE0,0xF0,0x06,0x30,0x08,0x04,0x18,0x08,0x1F,0xFF,0xFE,0x04,0x0E,0x08,0x07,0x87,0xF0,0x03,0x81,0xE0,0x00,0x00,0x00,0x00,0x00,0x00},/*"$",4*/
{0x01,0xF0,0x00,0x06,0x0C,0x00,0x04,0x04,0x08,0x06,0x0C,0x70,0x01,0xF9,0xC0,0x00,0x0E,0x00,0x00,0x3B,0xE0,0x00,0xEC,0x18,0x07,0x08,0x08,0x04,0x0C,0x18,0x00,0x03,0xE0,0x00,0x00,0x00},/*"%",5*/
{0x00,0x01,0xE0,0x00,0x07,0xF0,0x03,0xF8,0x18,0x04,0x1C,0x08,0x04,0x17,0x08,0x07,0xE1,0xD0,0x03,0xC0,0xE0,0x00,0x23,0xB0,0x00,0x3C,0x08,0x00,0x20,0x08,0x00,0x00,0x10,0x00,0x00,0x00},/*"&",6*/
{0x00,0x00,0x00,0x01,0x00,0x00,0x31,0x00,0x00,0x32,0x00,0x00,0x1C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"'",7*/
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7F,0x00,0x01,0xFF,0xC0,0x07,0x80,0xF0,0x0C,0x00,0x18,0x10,0x00,0x04,0x20,0x00,0x02,0x00,0x00,0x00},/*"(",8*/
{0x00,0x00,0x00,0x20,0x00,0x02,0x10,0x00,0x04,0x0C,0x00,0x18,0x07,0x80,0xF0,0x01,0xFF,0xC0,0x00,0x7F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*")",9*/
{0x00,0x00,0x00,0x00,0x42,0x00,0x00,0x66,0x00,0x00,0x66,0x00,0x00,0x3C,0x00,0x00,0x18,0x00,0x03,0xFF,0xC0,0x00,0x18,0x00,0x00,0x3C,0x00,0x00,0x66,0x00,0x00,0x66,0x00,0x00,0x42,0x00},/*"*",10*/
{0x00,0x00,0x00,0x00,0x08,0x00,0x00,0x08,0x00,0x00,0x08,0x00,0x00,0x08,0x00,0x00,0x08,0x00,0x01,0xFF,0xC0,0x00,0x08,0x00,0x00,0x08,0x00,0x00,0x08,0x00,0x00,0x08,0x00,0x00,0x08,0x00},/*"+",11*/
{0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x31,0x00,0x00,0x32,0x00,0x00,0x1C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*",",12*/
{0x00,0x00,0x00,0x00,0x08,0x00,0x00,0x08,0x00,0x00,0x08,0x00,0x00,0x08,0x00,0x00,0x08,0x00,0x00,0x08,0x00,0x00,0x08,0x00,0x00,0x08,0x00,0x00,0x08,0x00,0x00,0x08,0x00,0x00,0x00,0x00},/*"-",13*/
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x38,0x00,0x00,0x38,0x00,0x00,0x38,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*".",14*/
{0x00,0x00,0x00,0x00,0x00,0x06,0x00,0x00,0x1C,0x00,0x00,0x70,0x00,0x01,0x80,0x00,0x0E,0x00,0x00,0x38,0x00,0x00,0xC0,0x00,0x07,0x00,0x00,0x1C,0x00,0x00,0x30,0x00,0x00,0x00,0x00,0x00},/*"/",15*/
{0x00,0x00,0x00,0x00,0x7F,0x80,0x01,0xFF,0xE0,0x03,0x80,0x70,0x06,0x00,0x18,0x04,0x00,0x08,0x04,0x00,0x08,0x06,0x00,0x18,0x03,0x80,0x70,0x01,0xFF,0xE0,0x00,0x7F,0x80,0x00,0x00,0x00},/*"0",16*/
{0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x08,0x01,0x00,0x08,0x01,0x00,0x08,0x03,0xFF,0xF8,0x07,0xFF,0xF8,0x00,0x00,0x08,0x00,0x00,0x08,0x00,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x00},/*"1",17*/
{0x00,0x00,0x00,0x01,0xC0,0x38,0x02,0xC0,0x58,0x04,0x00,0x98,0x04,0x01,0x18,0x04,0x02,0x18,0x04,0x04,0x18,0x06,0x1C,0x18,0x03,0xF8,0x18,0x01,0xE0,0xF8,0x00,0x00,0x00,0x00,0x00,0x00},/*"2",18*/
{0x00,0x00,0x00,0x01,0xC0,0xE0,0x03,0xC0,0xF0,0x04,0x00,0x08,0x04,0x08,0x08,0x04,0x08,0x08,0x06,0x18,0x08,0x03,0xF4,0x18,0x01,0xE7,0xF0,0x00,0x01,0xE0,0x00,0x00,0x00,0x00,0x00,0x00},/*"3",19*/
{0x00,0x00,0x00,0x00,0x03,0x00,0x00,0x0D,0x00,0x00,0x11,0x00,0x00,0x61,0x00,0x00,0x81,0x08,0x03,0x01,0x08,0x07,0xFF,0xF8,0x0F,0xFF,0xF8,0x00,0x01,0x08,0x00,0x01,0x08,0x00,0x00,0x00},/*"4",20*/
{0x00,0x00,0x00,0x00,0x00,0xE0,0x07,0xFC,0xD0,0x06,0x08,0x08,0x06,0x10,0x08,0x06,0x10,0x08,0x06,0x10,0x08,0x06,0x18,0x38,0x06,0x0F,0xF0,0x06,0x07,0xC0,0x00,0x00,0x00,0x00,0x00,0x00},/*"5",21*/
{0x00,0x00,0x00,0x00,0x3F,0x80,0x01,0xFF,0xE0,0x03,0x84,0x30,0x02,0x08,0x18,0x04,0x10,0x08,0x04,0x10,0x08,0x04,0x10,0x08,0x07,0x18,0x10,0x03,0x0F,0xF0,0x00,0x07,0xC0,0x00,0x00,0x00},/*"6",22*/
{0x00,0x00,0x00,0x00,0x00,0x00,0x03,0xC0,0x00,0x07,0x00,0x00,0x06,0x00,0x00,0x06,0x00,0xF8,0x06,0x07,0xF8,0x06,0x18,0x00,0x06,0xE0,0x00,0x07,0x00,0x00,0x06,0x00,0x00,0x00,0x00,0x00},/*"7",23*/
{0x00,0x00,0x00,0x01,0xE1,0xE0,0x03,0xF7,0xF0,0x06,0x34,0x10,0x04,0x18,0x08,0x04,0x18,0x08,0x04,0x0C,0x08,0x04,0x0C,0x08,0x06,0x16,0x18,0x03,0xF3,0xF0,0x01,0xC1,0xE0,0x00,0x00,0x00},/*"8",24*/
{0x00,0x00,0x00,0x00,0xF8,0x00,0x03,0xFC,0x30,0x03,0x06,0x38,0x04,0x02,0x08,0x04,0x02,0x08,0x04,0x02,0x08,0x04,0x04,0x10,0x03,0x08,0xF0,0x01,0xFF,0xC0,0x00,0x7F,0x00,0x00,0x00,0x00},/*"9",25*/
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x70,0x38,0x00,0x70,0x38,0x00,0x70,0x38,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*":",26*/
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x1A,0x00,0x30,0x1C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*";",27*/
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x00,0x00,0x14,0x00,0x00,0x22,0x00,0x00,0x41,0x00,0x00,0x80,0x80,0x01,0x00,0x40,0x02,0x00,0x20,0x04,0x00,0x10,0x08,0x00,0x08,0x00,0x00,0x00},/*"<",28*/
{0x00,0x00,0x00,0x00,0x21,0x00,0x00,0x21,0x00,0x00,0x21,0x00,0x00,0x21,0x00,0x00,0x21,0x00,0x00,0x21,0x00,0x00,0x21,0x00,0x00,0x21,0x00,0x00,0x21,0x00,0x00,0x21,0x00,0x00,0x00,0x00},/*"=",29*/
{0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x00,0x08,0x04,0x00,0x10,0x02,0x00,0x20,0x01,0x00,0x40,0x00,0x80,0x80,0x00,0x41,0x00,0x00,0x22,0x00,0x00,0x14,0x00,0x00,0x08,0x00,0x00,0x00,0x00},/*">",30*/
{0x00,0x00,0x00,0x03,0xC0,0x00,0x04,0xC0,0x00,0x04,0x00,0x00,0x08,0x00,0x38,0x08,0x0F,0x38,0x08,0x08,0x38,0x08,0x10,0x00,0x0C,0x30,0x00,0x07,0xE0,0x00,0x03,0xC0,0x00,0x00,0x00,0x00},/*"?",31*/
{0x00,0x00,0x00,0x00,0x3F,0x80,0x00,0xFF,0xE0,0x03,0x80,0x70,0x02,0x0F,0x10,0x06,0x70,0x88,0x04,0xC0,0x88,0x04,0x83,0x08,0x04,0x7F,0x88,0x02,0xC0,0x90,0x03,0x01,0x20,0x00,0xFE,0x40},/*"@",32*/
{0x00,0x00,0x08,0x00,0x00,0x18,0x00,0x01,0xF8,0x00,0x3E,0x08,0x01,0xC2,0x00,0x07,0x02,0x00,0x07,0xE2,0x00,0x00,0xFE,0x00,0x00,0x1F,0xC8,0x00,0x01,0xF8,0x00,0x00,0x38,0x00,0x00,0x08},/*"A",33*/
{0x04,0x00,0x08,0x07,0xFF,0xF8,0x07,0xFF,0xF8,0x04,0x08,0x08,0x04,0x08,0x08,0x04,0x08,0x08,0x04,0x08,0x08,0x06,0x18,0x08,0x03,0xF4,0x18,0x01,0xE7,0xF0,0x00,0x01,0xE0,0x00,0x00,0x00},/*"B",34*/
{0x00,0x00,0x00,0x00,0x3F,0x80,0x01,0xFF,0xE0,0x03,0x80,0x70,0x02,0x00,0x18,0x04,0x00,0x08,0x04,0x00,0x08,0x04,0x00,0x08,0x04,0x00,0x10,0x06,0x00,0x20,0x07,0x80,0xC0,0x00,0x00,0x00},/*"C",35*/
{0x04,0x00,0x08,0x07,0xFF,0xF8,0x07,0xFF,0xF8,0x04,0x00,0x08,0x04,0x00,0x08,0x04,0x00,0x08,0x04,0x00,0x18,0x02,0x00,0x10,0x03,0x80,0x70,0x01,0xFF,0xE0,0x00,0x7F,0x80,0x00,0x00,0x00},/*"D",36*/
{0x04,0x00,0x08,0x07,0xFF,0xF8,0x07,0xFF,0xF8,0x04,0x08,0x08,0x04,0x08,0x08,0x04,0x08,0x08,0x04,0x08,0x08,0x04,0x3E,0x08,0x04,0x00,0x08,0x06,0x00,0x18,0x01,0x00,0x60,0x00,0x00,0x00},/*"E",37*/
{0x04,0x00,0x08,0x07,0xFF,0xF8,0x07,0xFF,0xF8,0x04,0x08,0x08,0x04,0x08,0x00,0x04,0x08,0x00,0x04,0x08,0x00,0x04,0x3E,0x00,0x06,0x00,0x00,0x06,0x00,0x00,0x01,0x80,0x00,0x00,0x00,0x00},/*"F",38*/
{0x00,0x00,0x00,0x00,0x3F,0x80,0x01,0xFF,0xE0,0x03,0x80,0x70,0x06,0x00,0x18,0x04,0x00,0x08,0x04,0x02,0x08,0x04,0x02,0x08,0x02,0x03,0xF0,0x07,0x83,0xF0,0x00,0x02,0x00,0x00,0x02,0x00},/*"G",39*/
{0x04,0x00,0x08,0x07,0xFF,0xF8,0x07,0xFF,0xF8,0x04,0x08,0x08,0x00,0x08,0x00,0x00,0x08,0x00,0x00,0x08,0x00,0x00,0x08,0x00,0x04,0x08,0x08,0x07,0xFF,0xF8,0x07,0xFF,0xF8,0x04,0x00,0x08},/*"H",40*/
{0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x08,0x04,0x00,0x08,0x04,0x00,0x08,0x07,0xFF,0xF8,0x07,0xFF,0xF8,0x04,0x00,0x08,0x04,0x00,0x08,0x04,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x00},/*"I",41*/
{0x00,0x00,0x00,0x00,0x00,0x06,0x00,0x00,0x07,0x00,0x00,0x01,0x04,0x00,0x01,0x04,0x00,0x01,0x04,0x00,0x03,0x07,0xFF,0xFE,0x07,0xFF,0xFC,0x04,0x00,0x00,0x04,0x00,0x00,0x04,0x00,0x00},/*"J",42*/
{0x04,0x00,0x08,0x07,0xFF,0xF8,0x07,0xFF,0xF8,0x04,0x0C,0x08,0x00,0x18,0x00,0x00,0x3E,0x00,0x04,0xC7,0x80,0x05,0x03,0xC8,0x06,0x00,0xF8,0x04,0x00,0x38,0x04,0x00,0x18,0x00,0x00,0x08},/*"K",43*/
{0x04,0x00,0x08,0x07,0xFF,0xF8,0x07,0xFF,0xF8,0x04,0x00,0x08,0x00,0x00,0x08,0x00,0x00,0x08,0x00,0x00,0x08,0x00,0x00,0x08,0x00,0x00,0x08,0x00,0x00,0x18,0x00,0x00,0x60,0x00,0x00,0x00},/*"L",44*/
{0x04,0x00,0x08,0x07,0xFF,0xF8,0x07,0x80,0x08,0x07,0xFC,0x00,0x00,0x7F,0xC0,0x00,0x03,0xF8,0x00,0x07,0xC0,0x00,0x78,0x00,0x07,0x80,0x08,0x07,0xFF,0xF8,0x07,0xFF,0xF8,0x04,0x00,0x08},/*"M",45*/
{0x04,0x00,0x08,0x07,0xFF,0xF8,0x07,0x00,0x08,0x03,0xC0,0x00,0x00,0xE0,0x00,0x00,0x38,0x00,0x00,0x1E,0x00,0x00,0x07,0x00,0x00,0x01,0xC0,0x04,0x00,0xF0,0x07,0xFF,0xF8,0x04,0x00,0x00},/*"N",46*/
{0x00,0x00,0x00,0x00,0x7F,0x80,0x01,0xFF,0xE0,0x03,0x80,0x70,0x06,0x00,0x18,0x04,0x00,0x08,0x04,0x00,0x08,0x06,0x00,0x18,0x03,0x00,0x30,0x01,0xFF,0xE0,0x00,0x7F,0x80,0x00,0x00,0x00},/*"O",47*/
{0x04,0x00,0x08,0x07,0xFF,0xF8,0x07,0xFF,0xF8,0x04,0x04,0x08,0x04,0x04,0x00,0x04,0x04,0x00,0x04,0x04,0x00,0x04,0x04,0x00,0x06,0x0C,0x00,0x03,0xF8,0x00,0x01,0xF0,0x00,0x00,0x00,0x00},/*"P",48*/
{0x00,0x00,0x00,0x00,0x7F,0x80,0x01,0xFF,0xE0,0x03,0x80,0x70,0x06,0x00,0x88,0x04,0x00,0x88,0x04,0x00,0xC8,0x06,0x00,0x3C,0x03,0x00,0x3E,0x01,0xFF,0xE6,0x00,0x7F,0x84,0x00,0x00,0x00},/*"Q",49*/
{0x04,0x00,0x08,0x07,0xFF,0xF8,0x07,0xFF,0xF8,0x04,0x08,0x08,0x04,0x08,0x00,0x04,0x0C,0x00,0x04,0x0F,0x00,0x04,0x0B,0xC0,0x06,0x10,0xF0,0x03,0xF0,0x38,0x01,0xE0,0x08,0x00,0x00,0x08},/*"R",50*/
{0x00,0x00,0x00,0x01,0xE0,0xF8,0x03,0xF0,0x30,0x06,0x30,0x10,0x04,0x18,0x08,0x04,0x18,0x08,0x04,0x0C,0x08,0x04,0x0C,0x08,0x02,0x06,0x18,0x02,0x07,0xF0,0x07,0x81,0xE0,0x00,0x00,0x00},/*"S",51*/
{0x01,0x80,0x00,0x06,0x00,0x00,0x04,0x00,0x00,0x04,0x00,0x00,0x04,0x00,0x08,0x07,0xFF,0xF8,0x07,0xFF,0xF8,0x04,0x00,0x08,0x04,0x00,0x00,0x04,0x00,0x00,0x06,0x00,0x00,0x01,0x80,0x00},/*"T",52*/
{0x04,0x00,0x00,0x07,0xFF,0xE0,0x07,0xFF,0xF0,0x04,0x00,0x18,0x00,0x00,0x08,0x00,0x00,0x08,0x00,0x00,0x08,0x00,0x00,0x08,0x00,0x00,0x08,0x04,0x00,0x10,0x07,0xFF,0xE0,0x04,0x00,0x00},/*"U",53*/
{0x04,0x00,0x00,0x06,0x00,0x00,0x07,0xE0,0x00,0x07,0xFE,0x00,0x04,0x1F,0xE0,0x00,0x01,0xF8,0x00,0x00,0x38,0x00,0x01,0xE0,0x04,0x3E,0x00,0x07,0xC0,0x00,0x06,0x00,0x00,0x04,0x00,0x00},/*"V",54*/
{0x04,0x00,0x00,0x07,0xE0,0x00,0x07,0xFF,0xC0,0x04,0x1F,0xF8,0x00,0x07,0xC0,0x07,0xF8,0x00,0x07,0xFF,0x80,0x04,0x3F,0xF8,0x00,0x07,0xC0,0x04,0xF8,0x00,0x07,0x00,0x00,0x04,0x00,0x00},/*"W",55*/
{0x00,0x00,0x00,0x04,0x00,0x08,0x06,0x00,0x18,0x07,0xC0,0x78,0x05,0xF1,0xC8,0x00,0x3E,0x00,0x00,0x1F,0x80,0x04,0x63,0xE8,0x07,0x80,0xF8,0x06,0x00,0x18,0x04,0x00,0x08,0x00,0x00,0x00},/*"X",56*/
{0x04,0x00,0x00,0x06,0x00,0x00,0x07,0x80,0x00,0x07,0xE0,0x08,0x04,0x7C,0x08,0x00,0x1F,0xF8,0x00,0x07,0xF8,0x00,0x18,0x08,0x04,0xE0,0x08,0x07,0x00,0x00,0x06,0x00,0x00,0x04,0x00,0x00},/*"Y",57*/
{0x00,0x00,0x00,0x01,0x00,0x08,0x06,0x00,0x38,0x04,0x00,0xF8,0x04,0x03,0xE8,0x04,0x0F,0x08,0x04,0x7C,0x08,0x05,0xF0,0x08,0x07,0xC0,0x08,0x07,0x00,0x18,0x04,0x00,0x60,0x00,0x00,0x00},/*"Z",58*/
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3F,0xFF,0xFE,0x20,0x00,0x02,0x20,0x00,0x02,0x20,0x00,0x02,0x20,0x00,0x02,0x20,0x00,0x02,0x00,0x00,0x00},/*"[",59*/
{0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x00,0x00,0x07,0x00,0x00,0x00,0xC0,0x00,0x00,0x38,0x00,0x00,0x06,0x00,0x00,0x01,0xC0,0x00,0x00,0x30,0x00,0x00,0x0E,0x00,0x00,0x01,0x00,0x00,0x00},/*"\",60*/
{0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x00,0x02,0x20,0x00,0x02,0x20,0x00,0x02,0x20,0x00,0x02,0x20,0x00,0x02,0x3F,0xFF,0xFE,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"]",61*/
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x00,0x00,0x10,0x00,0x00,0x30,0x00,0x00,0x20,0x00,0x00,0x30,0x00,0x00,0x10,0x00,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"^",62*/
{0x00,0x00,0x01,0x00,0x00,0x01,0x00,0x00,0x01,0x00,0x00,0x01,0x00,0x00,0x01,0x00,0x00,0x01,0x00,0x00,0x01,0x00,0x00,0x01,0x00,0x00,0x01,0x00,0x00,0x01,0x00,0x00,0x01,0x00,0x00,0x01},/*"_",63*/
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x00,0x00,0x20,0x00,0x00,0x10,0x00,0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"`",64*/
{0x00,0x00,0x00,0x00,0x00,0xF0,0x00,0x19,0xF8,0x00,0x1B,0x18,0x00,0x22,0x08,0x00,0x26,0x08,0x00,0x24,0x08,0x00,0x24,0x10,0x00,0x3F,0xF8,0x00,0x1F,0xF8,0x00,0x00,0x08,0x00,0x00,0x18},/*"a",65*/
{0x00,0x00,0x00,0x04,0x00,0x00,0x07,0xFF,0xF8,0x0F,0xFF,0xF0,0x00,0x18,0x18,0x00,0x10,0x08,0x00,0x20,0x08,0x00,0x20,0x08,0x00,0x30,0x18,0x00,0x1F,0xF0,0x00,0x0F,0xC0,0x00,0x00,0x00},/*"b",66*/
{0x00,0x00,0x00,0x00,0x07,0xC0,0x00,0x1F,0xF0,0x00,0x18,0x30,0x00,0x20,0x08,0x00,0x20,0x08,0x00,0x20,0x08,0x00,0x3C,0x08,0x00,0x1C,0x10,0x00,0x00,0x60,0x00,0x00,0x00,0x00,0x00,0x00},/*"c",67*/
{0x00,0x00,0x00,0x00,0x07,0xC0,0x00,0x1F,0xF0,0x00,0x38,0x18,0x00,0x20,0x08,0x00,0x20,0x08,0x00,0x20,0x08,0x04,0x10,0x10,0x07,0xFF,0xF8,0x0F,0xFF,0xF0,0x00,0x00,0x10,0x00,0x00,0x00},/*"d",68*/
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0xC0,0x00,0x1F,0xF0,0x00,0x12,0x30,0x00,0x22,0x18,0x00,0x22,0x08,0x00,0x22,0x08,0x00,0x32,0x08,0x00,0x1E,0x10,0x00,0x0E,0x20,0x00,0x00,0x00},/*"e",69*/
{0x00,0x00,0x00,0x00,0x20,0x00,0x00,0x20,0x08,0x00,0x20,0x08,0x01,0xFF,0xF8,0x03,0xFF,0xF8,0x06,0x20,0x08,0x04,0x20,0x08,0x04,0x20,0x08,0x07,0x20,0x00,0x03,0x00,0x00,0x00,0x00,0x00},/*"f",70*/
{0x00,0x00,0x00,0x00,0x00,0x0E,0x00,0x0E,0x6E,0x00,0x1F,0xF3,0x00,0x31,0xB1,0x00,0x20,0xB1,0x00,0x20,0xB1,0x00,0x31,0x91,0x00,0x1F,0x13,0x00,0x2E,0x1E,0x00,0x20,0x0E,0x00,0x30,0x00},/*"g",71*/
{0x00,0x00,0x00,0x04,0x00,0x08,0x07,0xFF,0xF8,0x0F,0xFF,0xF8,0x00,0x10,0x08,0x00,0x20,0x00,0x00,0x20,0x00,0x00,0x20,0x08,0x00,0x3F,0xF8,0x00,0x1F,0xF8,0x00,0x00,0x08,0x00,0x00,0x00},/*"h",72*/
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x08,0x00,0x20,0x08,0x00,0x20,0x08,0x06,0x3F,0xF8,0x06,0x3F,0xF8,0x00,0x00,0x08,0x00,0x00,0x08,0x00,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x00},/*"i",73*/
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x00,0x03,0x00,0x20,0x01,0x00,0x20,0x01,0x00,0x20,0x03,0x06,0x3F,0xFE,0x06,0x3F,0xFC,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"j",74*/
{0x00,0x00,0x00,0x04,0x00,0x08,0x07,0xFF,0xF8,0x0F,0xFF,0xF8,0x00,0x01,0x88,0x00,0x03,0x00,0x00,0x2F,0xC0,0x00,0x38,0xF8,0x00,0x20,0x38,0x00,0x20,0x08,0x00,0x00,0x08,0x00,0x00,0x00},/*"k",75*/
{0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x08,0x04,0x00,0x08,0x04,0x00,0x08,0x07,0xFF,0xF8,0x0F,0xFF,0xF8,0x00,0x00,0x08,0x00,0x00,0x08,0x00,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x00},/*"l",76*/
{0x00,0x20,0x08,0x00,0x3F,0xF8,0x00,0x3F,0xF8,0x00,0x10,0x08,0x00,0x20,0x00,0x00,0x3F,0xF8,0x00,0x3F,0xF8,0x00,0x10,0x08,0x00,0x20,0x00,0x00,0x3F,0xF8,0x00,0x3F,0xF8,0x00,0x00,0x08},/*"m",77*/
{0x00,0x00,0x00,0x00,0x20,0x08,0x00,0x3F,0xF8,0x00,0x3F,0xF8,0x00,0x10,0x08,0x00,0x10,0x00,0x00,0x20,0x00,0x00,0x20,0x08,0x00,0x3F,0xF8,0x00,0x1F,0xF8,0x00,0x00,0x08,0x00,0x00,0x00},/*"n",78*/
{0x00,0x00,0x00,0x00,0x07,0xC0,0x00,0x0F,0xF0,0x00,0x18,0x30,0x00,0x30,0x08,0x00,0x20,0x08,0x00,0x20,0x08,0x00,0x30,0x08,0x00,0x18,0x30,0x00,0x0F,0xF0,0x00,0x07,0xC0,0x00,0x00,0x00},/*"o",79*/
{0x00,0x00,0x00,0x00,0x20,0x01,0x00,0x3F,0xFF,0x00,0x3F,0xFF,0x00,0x10,0x11,0x00,0x20,0x09,0x00,0x20,0x08,0x00,0x20,0x08,0x00,0x30,0x38,0x00,0x1F,0xF0,0x00,0x0F,0xC0,0x00,0x00,0x00},/*"p",80*/
{0x00,0x00,0x00,0x00,0x07,0xC0,0x00,0x1F,0xF0,0x00,0x38,0x18,0x00,0x20,0x08,0x00,0x20,0x08,0x00,0x20,0x09,0x00,0x10,0x11,0x00,0x1F,0xFF,0x00,0x3F,0xFF,0x00,0x00,0x01,0x00,0x00,0x00},/*"q",81*/
{0x00,0x20,0x08,0x00,0x20,0x08,0x00,0x20,0x08,0x00,0x3F,0xF8,0x00,0x3F,0xF8,0x00,0x08,0x08,0x00,0x10,0x08,0x00,0x20,0x08,0x00,0x20,0x00,0x00,0x30,0x00,0x00,0x30,0x00,0x00,0x00,0x00},/*"r",82*/
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0C,0x78,0x00,0x1E,0x18,0x00,0x33,0x08,0x00,0x23,0x08,0x00,0x21,0x08,0x00,0x21,0x88,0x00,0x21,0x98,0x00,0x30,0xF0,0x00,0x38,0x60,0x00,0x00,0x00},/*"s",83*/
{0x00,0x00,0x00,0x00,0x20,0x00,0x00,0x20,0x00,0x00,0x20,0x00,0x00,0xFF,0xF0,0x03,0xFF,0xF8,0x00,0x20,0x08,0x00,0x20,0x08,0x00,0x20,0x08,0x00,0x00,0x30,0x00,0x00,0x00,0x00,0x00,0x00},/*"t",84*/
{0x00,0x00,0x00,0x00,0x20,0x00,0x00,0x3F,0xF0,0x00,0x7F,0xF8,0x00,0x00,0x18,0x00,0x00,0x08,0x00,0x00,0x08,0x00,0x20,0x10,0x00,0x3F,0xF8,0x00,0x7F,0xF0,0x00,0x00,0x10,0x00,0x00,0x00},/*"u",85*/
{0x00,0x00,0x00,0x00,0x20,0x00,0x00,0x30,0x00,0x00,0x3C,0x00,0x00,0x3F,0x80,0x00,0x23,0xF0,0x00,0x00,0x78,0x00,0x00,0x70,0x00,0x23,0x80,0x00,0x3C,0x00,0x00,0x30,0x00,0x00,0x20,0x00},/*"v",86*/
{0x00,0x20,0x00,0x00,0x3C,0x00,0x00,0x3F,0xE0,0x00,0x23,0xF8,0x00,0x00,0xE0,0x00,0x27,0x00,0x00,0x3E,0x00,0x00,0x3F,0xE0,0x00,0x21,0xF8,0x00,0x01,0xE0,0x00,0x3E,0x00,0x00,0x20,0x00},/*"w",87*/
{0x00,0x00,0x00,0x00,0x20,0x08,0x00,0x20,0x08,0x00,0x38,0x38,0x00,0x3E,0x68,0x00,0x27,0x80,0x00,0x03,0xC8,0x00,0x2C,0xF8,0x00,0x38,0x38,0x00,0x20,0x18,0x00,0x20,0x08,0x00,0x00,0x00},/*"x",88*/
{0x00,0x00,0x00,0x00,0x20,0x00,0x00,0x30,0x03,0x00,0x3C,0x01,0x00,0x3F,0x83,0x00,0x23,0xEC,0x00,0x00,0x70,0x00,0x23,0x80,0x00,0x3C,0x00,0x00,0x20,0x00,0x00,0x20,0x00,0x00,0x00,0x00},/*"y",89*/
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x38,0x08,0x00,0x20,0x38,0x00,0x20,0xF8,0x00,0x23,0xE8,0x00,0x2F,0x88,0x00,0x3E,0x08,0x00,0x38,0x08,0x00,0x20,0x18,0x00,0x00,0x70,0x00,0x00,0x00},/*"z",90*/
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x00,0x00,0x14,0x00,0x1F,0xF7,0xFC,0x30,0x00,0x06,0x20,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00},/*"{",91*/
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"|",92*/
{0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x00,0x02,0x30,0x00,0x06,0x1F,0xF7,0xFC,0x00,0x14,0x00,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"}",93*/
{0x00,0x00,0x00,0x18,0x00,0x00,0x60,0x00,0x00,0x40,0x00,0x00,0x40,0x00,0x00,0x20,0x00,0x00,0x10,0x00,0x00,0x08,0x00,0x00,0x04,0x00,0x00,0x04,0x00,0x00,0x0C,0x00,0x00,0x10,0x00,0x00},/*"~",94*/
};
//32*32 ASCII code
const unsigned char asc2_3216[95][128]={
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*" ",0*/
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0xF0,0x00,0xC0,0x07,0xFF,0xE1,0xE0,0x07,0xF0,0x01,0xE0,0x00,0x00,0x00,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"!",1*/
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x00,0x00,0x01,0xC0,0x00,0x00,0x07,0x80,0x00,0x00,0x1F,0x00,0x00,0x00,0x1E,0x00,0x00,0x00,0x1C,0x20,0x00,0x00,0x01,0xC0,0x00,0x00,0x07,0x80,0x00,0x00,0x1F,0x00,0x00,0x00,0x1E,0x00,0x00,0x00,0x1C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*""",2*/
{0x00,0x00,0x00,0x00,0x00,0x18,0x0C,0x00,0x00,0x18,0x0C,0x00,0x00,0x18,0x0F,0xE0,0x00,0x1F,0xFC,0x00,0x03,0xF8,0x0C,0x00,0x00,0x18,0x0C,0x00,0x00,0x18,0x0C,0x00,0x00,0x18,0x0C,0x00,0x00,0x18,0x0C,0x00,0x00,0x18,0x0F,0xE0,0x00,0x1F,0xFC,0x00,0x03,0xF8,0x0C,0x00,0x00,0x18,0x0C,0x00,0x00,0x18,0x0C,0x00,0x00,0x00,0x00,0x00},/*"#",3*/
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x80,0x00,0x78,0x07,0xC0,0x00,0xFC,0x06,0x40,0x01,0x0E,0x00,0x20,0x03,0x07,0x00,0x20,0x02,0x03,0x80,0x20,0x0F,0xFF,0xFF,0xFC,0x02,0x01,0xC0,0x20,0x02,0x00,0xE0,0x60,0x01,0x30,0x70,0x40,0x01,0xF0,0x3F,0x80,0x00,0xF0,0x1F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"$",4*/
{0x00,0xFE,0x00,0x00,0x01,0xFF,0x00,0x00,0x03,0x01,0x80,0x00,0x02,0x00,0x80,0x60,0x03,0x01,0x81,0xC0,0x01,0xFF,0x07,0x00,0x00,0xFE,0x18,0x00,0x00,0x00,0xE0,0x00,0x00,0x03,0xBF,0x00,0x00,0x0C,0xFF,0xC0,0x00,0x71,0x80,0x60,0x01,0xC1,0x00,0x20,0x03,0x01,0x80,0x60,0x00,0x00,0xFF,0xC0,0x00,0x00,0x3F,0x00,0x00,0x00,0x00,0x00},/*"%",5*/
{0x00,0x00,0x1F,0x00,0x00,0x00,0x7F,0xC0,0x00,0xFC,0xC0,0xC0,0x01,0xFF,0x80,0x60,0x03,0x03,0xE0,0x20,0x02,0x02,0x78,0x20,0x02,0x06,0x1E,0x20,0x03,0xFC,0x07,0x40,0x01,0xF0,0x03,0x80,0x00,0x01,0x03,0xC0,0x00,0x01,0x1C,0x60,0x00,0x01,0xE0,0x20,0x00,0x01,0x00,0x20,0x00,0x01,0x00,0x40,0x00,0x00,0x01,0x80,0x00,0x00,0x00,0x00},/*"&",6*/
{0x00,0x00,0x00,0x00,0x00,0x20,0x00,0x00,0x1C,0x60,0x00,0x00,0x1C,0x40,0x00,0x00,0x1F,0x80,0x00,0x00,0x0F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"'",7*/
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0xF8,0x00,0x00,0x3F,0xFF,0x00,0x00,0x78,0x07,0xC0,0x01,0xC0,0x00,0xE0,0x03,0x00,0x00,0x30,0x04,0x00,0x00,0x08,0x08,0x00,0x00,0x04,0x10,0x00,0x00,0x02,0x00,0x00,0x00,0x00},/*"(",8*/
{0x00,0x00,0x00,0x00,0x10,0x00,0x00,0x02,0x08,0x00,0x00,0x04,0x04,0x00,0x00,0x08,0x03,0x00,0x00,0x30,0x01,0xC0,0x00,0xE0,0x00,0x78,0x07,0xC0,0x00,0x3F,0xFF,0x00,0x00,0x07,0xF8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*")",9*/
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0C,0x18,0x00,0x00,0x0E,0x38,0x00,0x00,0x0E,0x38,0x00,0x00,0x06,0x30,0x00,0x00,0x03,0x60,0x00,0x00,0x61,0x43,0x80,0x00,0xFF,0xFF,0x80,0x00,0x61,0x43,0x00,0x00,0x03,0x60,0x00,0x00,0x06,0x30,0x00,0x00,0x0E,0x38,0x00,0x00,0x0E,0x38,0x00,0x00,0x0C,0x18,0x00,0x00,0x00,0x00,0x00},/*"*",10*/
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x00,0x00,0x00,0x80,0x00,0x00,0x00,0x80,0x00,0x00,0x00,0x80,0x00,0x00,0x00,0x80,0x00,0x00,0x00,0x80,0x00,0x00,0x7F,0xFF,0x00,0x00,0x00,0x80,0x00,0x00,0x00,0x80,0x00,0x00,0x00,0x80,0x00,0x00,0x00,0x80,0x00,0x00,0x00,0x80,0x00,0x00,0x00,0x80,0x00,0x00,0x00,0x00,0x00},/*"+",11*/
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0xE3,0x00,0x00,0x00,0xE2,0x00,0x00,0x00,0xFC,0x00,0x00,0x00,0x78,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*",",12*/
{0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x00,0x00,0x00,0x80,0x00,0x00,0x00,0x80,0x00,0x00,0x00,0x80,0x00,0x00,0x00,0x80,0x00,0x00,0x00,0x80,0x00,0x00,0x00,0x80,0x00,0x00,0x00,0x80,0x00,0x00,0x00,0x80,0x00,0x00,0x00,0x80,0x00,0x00,0x00,0x80,0x00,0x00,0x00,0x80,0x00,0x00,0x00,0x80,0x00,0x00,0x00,0x80,0x00,0x00,0x00,0x00,0x00},/*"-",13*/
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC0,0x00,0x00,0x01,0xE0,0x00,0x00,0x01,0xE0,0x00,0x00,0x00,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*".",14*/
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0C,0x00,0x00,0x00,0x38,0x00,0x00,0x00,0xE0,0x00,0x00,0x03,0x80,0x00,0x00,0x0E,0x00,0x00,0x00,0x38,0x00,0x00,0x00,0xE0,0x00,0x00,0x03,0x80,0x00,0x00,0x0E,0x00,0x00,0x00,0x38,0x00,0x00,0x00,0xE0,0x00,0x00,0x03,0x80,0x00,0x00,0x0E,0x00,0x00,0x00,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"/",15*/
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0xF8,0x00,0x00,0x7F,0xFF,0x00,0x00,0xF0,0x07,0x80,0x01,0x80,0x00,0xC0,0x03,0x00,0x00,0x60,0x02,0x00,0x00,0x20,0x02,0x00,0x00,0x20,0x02,0x00,0x00,0x20,0x03,0x00,0x00,0x60,0x01,0x80,0x00,0xC0,0x00,0xE0,0x03,0x80,0x00,0x7F,0xFF,0x00,0x00,0x0F,0xF8,0x00,0x00,0x00,0x00,0x00},/*"0",16*/
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x00,0x20,0x00,0x80,0x00,0x20,0x00,0x80,0x00,0x20,0x00,0x80,0x00,0x60,0x01,0xFF,0xFF,0xE0,0x03,0xFF,0xFF,0xE0,0x00,0x00,0x00,0x60,0x00,0x00,0x00,0x20,0x00,0x00,0x00,0x20,0x00,0x00,0x00,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"1",17*/
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x78,0x00,0xE0,0x00,0x98,0x01,0x60,0x01,0x00,0x02,0x60,0x02,0x00,0x04,0x60,0x02,0x00,0x08,0x60,0x02,0x00,0x10,0x60,0x02,0x00,0x20,0x60,0x02,0x00,0x40,0x60,0x03,0x00,0x80,0x60,0x01,0x83,0x00,0x60,0x01,0xFE,0x00,0xE0,0x00,0x7C,0x07,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"2",18*/
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xF0,0x07,0x80,0x01,0xF0,0x07,0xC0,0x01,0x00,0x00,0x40,0x02,0x00,0x00,0x20,0x02,0x01,0x00,0x20,0x02,0x01,0x00,0x20,0x02,0x01,0x00,0x20,0x03,0x03,0x80,0x20,0x01,0x86,0x80,0x40,0x01,0xFC,0xC0,0xC0,0x00,0x78,0x7F,0x80,0x00,0x00,0x1E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"3",19*/
{0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x00,0x00,0x00,0x38,0x00,0x00,0x00,0x48,0x00,0x00,0x01,0x88,0x00,0x00,0x06,0x08,0x00,0x00,0x0C,0x08,0x10,0x00,0x30,0x08,0x10,0x00,0x40,0x08,0x10,0x01,0xFF,0xFF,0xF0,0x03,0xFF,0xFF,0xF0,0x03,0xFF,0xFF,0xF0,0x00,0x00,0x08,0x10,0x00,0x00,0x08,0x10,0x00,0x00,0x08,0x10,0x00,0x00,0x00,0x00},/*"4",20*/
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x80,0x00,0x1F,0x86,0x40,0x03,0xE1,0x00,0x20,0x03,0x02,0x00,0x20,0x03,0x04,0x00,0x20,0x03,0x04,0x00,0x20,0x03,0x04,0x00,0x20,0x03,0x04,0x00,0x20,0x03,0x06,0x00,0x40,0x03,0x03,0x01,0xC0,0x03,0x01,0xFF,0x80,0x03,0x00,0x7E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"5",21*/
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0xFC,0x00,0x00,0x3F,0xFF,0x00,0x00,0x70,0xC3,0x80,0x00,0x81,0x80,0xC0,0x01,0x01,0x00,0x60,0x03,0x02,0x00,0x20,0x02,0x02,0x00,0x20,0x02,0x02,0x00,0x20,0x02,0x02,0x00,0x20,0x02,0x03,0x00,0x40,0x01,0xC1,0x80,0xC0,0x00,0xC0,0xFF,0x80,0x00,0x00,0x7E,0x00,0x00,0x00,0x00,0x00},/*"6",22*/
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xF0,0x00,0x00,0x03,0xC0,0x00,0x00,0x03,0x80,0x00,0x00,0x03,0x00,0x00,0x00,0x03,0x00,0x07,0xE0,0x03,0x00,0x3F,0xE0,0x03,0x01,0xC0,0x00,0x03,0x06,0x00,0x00,0x03,0x18,0x00,0x00,0x03,0x60,0x00,0x00,0x03,0x80,0x00,0x00,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"7",23*/
{0x00,0x00,0x00,0x00,0x00,0x00,0x1F,0x00,0x00,0x78,0x3F,0x80,0x00,0xFC,0x60,0xC0,0x01,0x8E,0xC0,0x40,0x03,0x07,0x80,0x20,0x02,0x03,0x00,0x20,0x02,0x01,0x80,0x20,0x02,0x01,0x80,0x20,0x02,0x01,0xC0,0x20,0x03,0x01,0xE0,0x40,0x01,0x86,0x70,0xC0,0x00,0xFC,0x3F,0x80,0x00,0x78,0x1F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"8",24*/
{0x00,0x00,0x00,0x00,0x00,0x3F,0x00,0x00,0x00,0xFF,0x81,0xC0,0x01,0xC0,0xC1,0xC0,0x01,0x00,0x60,0x20,0x02,0x00,0x20,0x20,0x02,0x00,0x20,0x20,0x02,0x00,0x20,0x20,0x02,0x00,0x20,0x60,0x02,0x00,0x40,0xC0,0x01,0x00,0xC1,0x80,0x00,0xC1,0x8F,0x00,0x00,0x7F,0xFE,0x00,0x00,0x1F,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"9",25*/
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0xC0,0x00,0x07,0x81,0xE0,0x00,0x07,0x81,0xE0,0x00,0x03,0x00,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*":",26*/
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x00,0x66,0x00,0x06,0x00,0x78,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*";",27*/
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x00,0x00,0x01,0xC0,0x00,0x00,0x03,0x60,0x00,0x00,0x06,0x30,0x00,0x00,0x0C,0x18,0x00,0x00,0x18,0x0C,0x00,0x00,0x30,0x06,0x00,0x00,0x60,0x03,0x00,0x00,0xC0,0x01,0x80,0x01,0x00,0x00,0x40,0x02,0x00,0x00,0x20,0x04,0x00,0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"<",28*/
{0x00,0x00,0x00,0x00,0x00,0x04,0x10,0x00,0x00,0x04,0x10,0x00,0x00,0x04,0x10,0x00,0x00,0x04,0x10,0x00,0x00,0x04,0x10,0x00,0x00,0x04,0x10,0x00,0x00,0x04,0x10,0x00,0x00,0x04,0x10,0x00,0x00,0x04,0x10,0x00,0x00,0x04,0x10,0x00,0x00,0x04,0x10,0x00,0x00,0x04,0x10,0x00,0x00,0x04,0x10,0x00,0x00,0x04,0x10,0x00,0x00,0x00,0x00,0x00},/*"=",29*/
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x00,0x10,0x02,0x00,0x00,0x20,0x01,0x00,0x00,0x40,0x00,0xC0,0x01,0x80,0x00,0x60,0x03,0x00,0x00,0x30,0x06,0x00,0x00,0x18,0x0C,0x00,0x00,0x0C,0x18,0x00,0x00,0x06,0x30,0x00,0x00,0x03,0x60,0x00,0x00,0x01,0xC0,0x00,0x00,0x00,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*">",30*/
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x78,0x00,0x00,0x01,0xF8,0x00,0x00,0x02,0x38,0x00,0x00,0x02,0x00,0x00,0x00,0x04,0x00,0x00,0xC0,0x04,0x00,0x79,0xE0,0x04,0x00,0x81,0xE0,0x04,0x01,0x00,0xC0,0x04,0x03,0x00,0x00,0x02,0x02,0x00,0x00,0x03,0x06,0x00,0x00,0x01,0xFC,0x00,0x00,0x00,0xF8,0x00,0x00,0x00,0x00,0x00,0x00},/*"?",31*/
{0x00,0x00,0x00,0x00,0x00,0x0F,0xF8,0x00,0x00,0x3F,0xFE,0x00,0x00,0x70,0x07,0x80,0x00,0xC0,0x00,0xC0,0x01,0x01,0xF8,0x40,0x03,0x07,0xFC,0x20,0x02,0x1E,0x04,0x20,0x02,0x30,0x08,0x20,0x02,0x20,0x30,0x20,0x02,0x3F,0xFC,0x20,0x01,0x3F,0x04,0x40,0x01,0x80,0x0C,0xC0,0x00,0xE0,0x31,0x80,0x00,0x1F,0xC2,0x00,0x00,0x00,0x00,0x00},/*"@",32*/
{0x00,0x00,0x00,0x20,0x00,0x00,0x00,0x60,0x00,0x00,0x03,0xE0,0x00,0x00,0x3E,0x20,0x00,0x03,0xE0,0x20,0x00,0x3E,0x20,0x00,0x03,0xE0,0x20,0x00,0x03,0x80,0x20,0x00,0x07,0xFC,0x20,0x00,0x00,0x3F,0xE0,0x00,0x00,0x03,0xFE,0x20,0x00,0x00,0x3F,0xE0,0x00,0x00,0x01,0xE0,0x00,0x00,0x00,0x20,0x00,0x00,0x00,0x20,0x00,0x00,0x00,0x00},/*"A",33*/
{0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x20,0x02,0x00,0x00,0x20,0x03,0xFF,0xFF,0xE0,0x03,0xFF,0xFF,0xE0,0x02,0x01,0x00,0x20,0x02,0x01,0x00,0x20,0x02,0x01,0x00,0x20,0x02,0x01,0x00,0x20,0x02,0x01,0x00,0x20,0x03,0x03,0x00,0x20,0x01,0x86,0x80,0x60,0x01,0xFC,0xC0,0xC0,0x00,0xF8,0x7F,0x80,0x00,0x00,0x1F,0x00,0x00,0x00,0x00,0x00},/*"B",34*/
{0x00,0x00,0x00,0x00,0x00,0x07,0xF8,0x00,0x00,0x3F,0xFF,0x00,0x00,0x70,0x07,0x80,0x00,0xC0,0x00,0xC0,0x01,0x00,0x00,0x40,0x03,0x00,0x00,0x20,0x02,0x00,0x00,0x20,0x02,0x00,0x00,0x20,0x02,0x00,0x00,0x20,0x02,0x00,0x00,0x20,0x01,0x00,0x00,0x40,0x01,0x80,0x00,0xC0,0x03,0xC0,0x01,0x80,0x00,0x30,0x06,0x00,0x00,0x00,0x00,0x00},/*"C",35*/
{0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x20,0x02,0x00,0x00,0x20,0x03,0xFF,0xFF,0xE0,0x03,0xFF,0xFF,0xE0,0x02,0x00,0x00,0x20,0x02,0x00,0x00,0x20,0x02,0x00,0x00,0x20,0x02,0x00,0x00,0x20,0x03,0x00,0x00,0x60,0x01,0x00,0x00,0x40,0x01,0x80,0x00,0xC0,0x00,0xF0,0x07,0x80,0x00,0x7F,0xFE,0x00,0x00,0x0F,0xF8,0x00,0x00,0x00,0x00,0x00},/*"D",36*/
{0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x20,0x02,0x00,0x00,0x20,0x03,0xFF,0xFF,0xE0,0x03,0xFF,0xFF,0xE0,0x02,0x01,0x00,0x20,0x02,0x01,0x00,0x20,0x02,0x01,0x00,0x20,0x02,0x01,0x00,0x20,0x02,0x01,0x00,0x20,0x02,0x03,0x80,0x20,0x02,0x0F,0xE0,0x20,0x03,0x00,0x00,0x60,0x03,0xC0,0x00,0xE0,0x00,0x60,0x03,0x00,0x00,0x00,0x00,0x00},/*"E",37*/
{0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x20,0x02,0x00,0x00,0x20,0x03,0xFF,0xFF,0xE0,0x03,0xFF,0xFF,0xE0,0x02,0x01,0x00,0x20,0x02,0x01,0x00,0x20,0x02,0x01,0x00,0x00,0x02,0x01,0x00,0x00,0x02,0x01,0x00,0x00,0x02,0x01,0x00,0x00,0x02,0x03,0x80,0x00,0x03,0x0F,0xE0,0x00,0x03,0x00,0x00,0x00,0x03,0xC0,0x00,0x00,0x00,0x60,0x00,0x00},/*"F",38*/
{0x00,0x00,0x00,0x00,0x00,0x07,0xF8,0x00,0x00,0x3F,0xFE,0x00,0x00,0x70,0x07,0x80,0x01,0xC0,0x01,0xC0,0x01,0x00,0x00,0x40,0x03,0x00,0x00,0x20,0x02,0x00,0x00,0x20,0x02,0x00,0x00,0x20,0x02,0x00,0x00,0x20,0x01,0x00,0x20,0x20,0x01,0x00,0x20,0x40,0x03,0xC0,0x3F,0x80,0x00,0x30,0x3F,0x80,0x00,0x00,0x20,0x00,0x00,0x00,0x20,0x00},/*"G",39*/
{0x02,0x00,0x00,0x20,0x02,0x00,0x00,0x20,0x03,0xFF,0xFF,0xE0,0x03,0xFF,0xFF,0xE0,0x02,0x00,0x80,0x20,0x02,0x00,0x80,0x20,0x00,0x00,0x80,0x00,0x00,0x00,0x80,0x00,0x00,0x00,0x80,0x00,0x02,0x00,0x80,0x20,0x02,0x00,0x80,0x20,0x03,0xFF,0xFF,0xE0,0x03,0xFF,0xFF,0xE0,0x02,0x00,0x00,0x20,0x02,0x00,0x00,0x20,0x00,0x00,0x00,0x00},/*"H",40*/
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x20,0x02,0x00,0x00,0x20,0x02,0x00,0x00,0x20,0x02,0x00,0x00,0x20,0x03,0xFF,0xFF,0xE0,0x03,0xFF,0xFF,0xE0,0x02,0x00,0x00,0x20,0x02,0x00,0x00,0x20,0x02,0x00,0x00,0x20,0x02,0x00,0x00,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"I",41*/
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0E,0x00,0x00,0x00,0x0F,0x00,0x00,0x00,0x0F,0x00,0x00,0x00,0x01,0x02,0x00,0x00,0x01,0x02,0x00,0x00,0x01,0x02,0x00,0x00,0x03,0x02,0x00,0x00,0x06,0x03,0xFF,0xFF,0xFC,0x03,0xFF,0xFF,0xF8,0x02,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"J",42*/
{0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x20,0x02,0x00,0x00,0x20,0x03,0xFF,0xFF,0xE0,0x03,0xFF,0xFF,0xE0,0x02,0x00,0xC0,0x20,0x02,0x01,0x00,0x20,0x00,0x07,0x80,0x00,0x00,0x0F,0xE0,0x00,0x00,0x30,0xF8,0x00,0x02,0x60,0x3E,0x20,0x03,0x80,0x0F,0x20,0x03,0x00,0x03,0xE0,0x02,0x00,0x00,0xE0,0x02,0x00,0x00,0x20,0x00,0x00,0x00,0x20},/*"K",43*/
{0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x20,0x02,0x00,0x00,0x20,0x03,0xFF,0xFF,0xE0,0x03,0xFF,0xFF,0xE0,0x02,0x00,0x00,0x20,0x02,0x00,0x00,0x20,0x00,0x00,0x00,0x20,0x00,0x00,0x00,0x20,0x00,0x00,0x00,0x20,0x00,0x00,0x00,0x20,0x00,0x00,0x00,0x20,0x00,0x00,0x00,0x60,0x00,0x00,0x00,0xE0,0x00,0x00,0x03,0x00,0x00,0x00,0x00,0x00},/*"L",44*/
{0x02,0x00,0x00,0x20,0x02,0x00,0x00,0x20,0x03,0xFF,0xFF,0xE0,0x03,0xE0,0x00,0x20,0x03,0xFF,0x00,0x20,0x00,0x1F,0xF0,0x00,0x00,0x01,0xFF,0x80,0x00,0x00,0x0F,0xE0,0x00,0x00,0x1E,0x00,0x00,0x03,0xE0,0x00,0x00,0x3E,0x00,0x20,0x03,0xE0,0x00,0x20,0x03,0xFF,0xFF,0xE0,0x03,0xFF,0xFF,0xE0,0x02,0x00,0x00,0x20,0x02,0x00,0x00,0x20},/*"M",45*/
{0x02,0x00,0x00,0x20,0x02,0x00,0x00,0x20,0x03,0xFF,0xFF,0xE0,0x03,0x80,0x00,0x20,0x03,0xF0,0x00,0x20,0x00,0xFC,0x00,0x00,0x00,0x1F,0x00,0x00,0x00,0x07,0xC0,0x00,0x00,0x01,0xF0,0x00,0x00,0x00,0x7C,0x00,0x02,0x00,0x1F,0x80,0x02,0x00,0x07,0xE0,0x03,0xFF,0xFF,0xE0,0x02,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"N",46*/
{0x00,0x00,0x00,0x00,0x00,0x0F,0xF8,0x00,0x00,0x3F,0xFE,0x00,0x00,0xF0,0x07,0x80,0x01,0x80,0x00,0xC0,0x01,0x00,0x00,0x40,0x02,0x00,0x00,0x20,0x02,0x00,0x00,0x20,0x02,0x00,0x00,0x20,0x02,0x00,0x00,0x20,0x01,0x00,0x00,0x40,0x01,0x80,0x00,0xC0,0x00,0xF0,0x03,0x80,0x00,0x3F,0xFE,0x00,0x00,0x0F,0xF8,0x00,0x00,0x00,0x00,0x00},/*"O",47*/
{0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x20,0x02,0x00,0x00,0x20,0x03,0xFF,0xFF,0xE0,0x03,0xFF,0xFF,0xE0,0x02,0x00,0x80,0x20,0x02,0x00,0x80,0x20,0x02,0x00,0x80,0x00,0x02,0x00,0x80,0x00,0x02,0x00,0x80,0x00,0x02,0x00,0x80,0x00,0x03,0x01,0x80,0x00,0x01,0x83,0x00,0x00,0x00,0xFE,0x00,0x00,0x00,0x7C,0x00,0x00,0x00,0x00,0x00,0x00},/*"P",48*/
{0x00,0x00,0x00,0x00,0x00,0x0F,0xF8,0x00,0x00,0x7F,0xFF,0x00,0x00,0xF0,0x03,0x80,0x01,0x80,0x01,0xC0,0x01,0x00,0x06,0x40,0x02,0x00,0x04,0x20,0x02,0x00,0x04,0x20,0x02,0x00,0x06,0x20,0x02,0x00,0x03,0xE0,0x01,0x00,0x00,0xF8,0x01,0x80,0x00,0x5C,0x00,0xE0,0x03,0x8C,0x00,0x3F,0xFF,0x0C,0x00,0x0F,0xFC,0x18,0x00,0x00,0x00,0x00},/*"Q",49*/
{0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x20,0x02,0x00,0x00,0x20,0x03,0xFF,0xFF,0xE0,0x03,0xFF,0xFF,0xE0,0x02,0x01,0x00,0x20,0x02,0x01,0x00,0x20,0x02,0x01,0x80,0x00,0x02,0x01,0xE0,0x00,0x02,0x01,0xFC,0x00,0x03,0x03,0x3F,0x80,0x01,0x86,0x07,0xE0,0x01,0xFC,0x00,0xE0,0x00,0xF8,0x00,0x20,0x00,0x00,0x00,0x20,0x00,0x00,0x00,0x00},/*"R",50*/
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x78,0x06,0x00,0x00,0xFE,0x01,0xE0,0x01,0x86,0x00,0xC0,0x03,0x03,0x00,0x40,0x02,0x03,0x00,0x20,0x02,0x01,0x80,0x20,0x02,0x01,0x80,0x20,0x02,0x01,0xC0,0x20,0x02,0x00,0xC0,0x20,0x01,0x00,0xE0,0x60,0x01,0x80,0x70,0xC0,0x03,0xE0,0x3F,0x80,0x00,0x00,0x1F,0x00,0x00,0x00,0x00,0x00},/*"S",51*/
{0x00,0x00,0x00,0x00,0x00,0x60,0x00,0x00,0x03,0x80,0x00,0x00,0x03,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x02,0x00,0x00,0x20,0x02,0x00,0x00,0x20,0x03,0xFF,0xFF,0xE0,0x03,0xFF,0xFF,0xE0,0x02,0x00,0x00,0x20,0x02,0x00,0x00,0x20,0x02,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x03,0x80,0x00,0x00,0x00,0xE0,0x00,0x00,0x00,0x00,0x00,0x00},/*"T",52*/
{0x02,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x03,0xFF,0xFF,0x00,0x03,0xFF,0xFF,0xC0,0x02,0x00,0x00,0x40,0x02,0x00,0x00,0x60,0x00,0x00,0x00,0x20,0x00,0x00,0x00,0x20,0x00,0x00,0x00,0x20,0x00,0x00,0x00,0x20,0x02,0x00,0x00,0x40,0x02,0x00,0x00,0x80,0x03,0xFF,0xFF,0x00,0x02,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"U",53*/
{0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x03,0xC0,0x00,0x00,0x03,0xFC,0x00,0x00,0x02,0x3F,0xC0,0x00,0x00,0x03,0xF8,0x00,0x00,0x00,0x7F,0x80,0x00,0x00,0x07,0xE0,0x00,0x00,0x07,0x80,0x00,0x00,0x78,0x00,0x02,0x03,0xC0,0x00,0x02,0x3C,0x00,0x00,0x03,0xC0,0x00,0x00,0x02,0x00,0x00,0x00,0x02,0x00,0x00,0x00},/*"V",54*/
{0x02,0x00,0x00,0x00,0x03,0xC0,0x00,0x00,0x03,0xFF,0x80,0x00,0x02,0x3F,0xFE,0x00,0x02,0x00,0x7F,0xE0,0x00,0x00,0x0F,0x00,0x02,0x00,0xF0,0x00,0x03,0xEF,0x00,0x00,0x03,0xFF,0x80,0x00,0x02,0x0F,0xFE,0x00,0x00,0x00,0x3F,0xE0,0x00,0x00,0x1F,0x00,0x02,0x07,0xE0,0x00,0x03,0xF8,0x00,0x00,0x03,0x00,0x00,0x00,0x02,0x00,0x00,0x00},/*"W",55*/
{0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x20,0x02,0x00,0x00,0x20,0x03,0x80,0x00,0xE0,0x03,0xF0,0x03,0x20,0x02,0xFC,0x0C,0x20,0x02,0x1F,0x30,0x00,0x00,0x07,0xC0,0x00,0x00,0x07,0xF0,0x00,0x02,0x18,0x7C,0x00,0x02,0x60,0x1F,0x20,0x03,0x80,0x03,0xE0,0x02,0x00,0x00,0xE0,0x02,0x00,0x00,0x20,0x00,0x00,0x00,0x20,0x00,0x00,0x00,0x00},/*"X",56*/
{0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x03,0xC0,0x00,0x00,0x03,0xF8,0x00,0x00,0x02,0x3E,0x00,0x20,0x02,0x0F,0xC0,0x20,0x00,0x01,0xFF,0xE0,0x00,0x00,0x7F,0xE0,0x00,0x03,0x80,0x20,0x02,0x1C,0x00,0x20,0x02,0x70,0x00,0x00,0x03,0x80,0x00,0x00,0x02,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"Y",57*/
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x00,0x60,0x00,0xE0,0x03,0x80,0x03,0xE0,0x03,0x00,0x0F,0xA0,0x02,0x00,0x3E,0x20,0x02,0x00,0xF8,0x20,0x02,0x03,0xE0,0x20,0x02,0x0F,0x80,0x20,0x02,0x3E,0x00,0x20,0x02,0x78,0x00,0x20,0x03,0xE0,0x00,0x60,0x03,0x80,0x00,0xE0,0x02,0x00,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"Z",58*/
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1F,0xFF,0xFF,0xFC,0x10,0x00,0x00,0x04,0x10,0x00,0x00,0x04,0x10,0x00,0x00,0x04,0x10,0x00,0x00,0x04,0x10,0x00,0x00,0x04,0x10,0x00,0x00,0x04,0x10,0x00,0x00,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"[",59*/
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x03,0xC0,0x00,0x00,0x00,0x78,0x00,0x00,0x00,0x1E,0x00,0x00,0x00,0x03,0xC0,0x00,0x00,0x00,0xF0,0x00,0x00,0x00,0x1E,0x00,0x00,0x00,0x07,0x80,0x00,0x00,0x00,0xF0,0x00,0x00,0x00,0x3C,0x00,0x00,0x00,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"\",60*/
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x00,0x00,0x04,0x10,0x00,0x00,0x04,0x10,0x00,0x00,0x04,0x10,0x00,0x00,0x04,0x10,0x00,0x00,0x04,0x10,0x00,0x00,0x04,0x10,0x00,0x00,0x04,0x1F,0xFF,0xFF,0xFC,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"]",61*/
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x08,0x00,0x00,0x00,0x18,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x18,0x00,0x00,0x00,0x18,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"^",62*/
{0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x01},/*"_",63*/
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x18,0x00,0x00,0x00,0x08,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"`",64*/
{0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x80,0x00,0x01,0x8F,0xC0,0x00,0x03,0x8C,0x60,0x00,0x06,0x18,0x20,0x00,0x04,0x10,0x20,0x00,0x04,0x10,0x20,0x00,0x04,0x20,0x20,0x00,0x04,0x20,0x40,0x00,0x06,0x20,0x40,0x00,0x03,0xFF,0xC0,0x00,0x01,0xFF,0xE0,0x00,0x00,0x00,0x20,0x00,0x00,0x00,0x20,0x00,0x00,0x00,0xC0,0x00,0x00,0x00,0x00},/*"a",65*/
{0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x03,0xFF,0xFF,0xE0,0x07,0xFF,0xFF,0xC0,0x00,0x01,0x80,0xC0,0x00,0x02,0x00,0x60,0x00,0x02,0x00,0x20,0x00,0x04,0x00,0x20,0x00,0x04,0x00,0x20,0x00,0x04,0x00,0x20,0x00,0x06,0x00,0x40,0x00,0x03,0x00,0xC0,0x00,0x01,0xFF,0x80,0x00,0x00,0xFE,0x00,0x00,0x00,0x00,0x00},/*"b",66*/
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7E,0x00,0x00,0x01,0xFF,0x80,0x00,0x03,0x81,0xC0,0x00,0x02,0x00,0x40,0x00,0x06,0x00,0x20,0x00,0x04,0x00,0x20,0x00,0x04,0x00,0x20,0x00,0x04,0x00,0x20,0x00,0x06,0x00,0x20,0x00,0x03,0xC0,0x40,0x00,0x01,0xC0,0x80,0x00,0x00,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"c",67*/
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7E,0x00,0x00,0x01,0xFF,0x80,0x00,0x03,0x80,0xC0,0x00,0x06,0x00,0x60,0x00,0x04,0x00,0x20,0x00,0x04,0x00,0x20,0x00,0x04,0x00,0x20,0x02,0x04,0x00,0x40,0x02,0x02,0x00,0x80,0x03,0xFF,0xFF,0xE0,0x07,0xFF,0xFF,0xC0,0x00,0x00,0x00,0x40,0x00,0x00,0x00,0x40,0x00,0x00,0x00,0x00},/*"d",68*/
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7E,0x00,0x00,0x01,0xFF,0x80,0x00,0x03,0x11,0xC0,0x00,0x02,0x10,0x40,0x00,0x04,0x10,0x60,0x00,0x04,0x10,0x20,0x00,0x04,0x10,0x20,0x00,0x04,0x10,0x20,0x00,0x06,0x10,0x20,0x00,0x03,0x10,0x40,0x00,0x01,0xF0,0xC0,0x00,0x00,0x71,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"e",69*/
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x04,0x00,0x20,0x00,0x04,0x00,0x20,0x00,0x04,0x00,0x20,0x00,0x7F,0xFF,0xE0,0x01,0xFF,0xFF,0xE0,0x01,0x04,0x00,0x20,0x03,0x04,0x00,0x20,0x02,0x04,0x00,0x20,0x02,0x04,0x00,0x20,0x02,0x04,0x00,0x00,0x02,0x00,0x00,0x00,0x01,0xC0,0x00,0x00,0x01,0xC0,0x00,0x00},/*"f",70*/
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1C,0x00,0x00,0xE3,0x3E,0x00,0x03,0xFF,0xC2,0x00,0x02,0x0C,0xC3,0x00,0x04,0x04,0xC1,0x00,0x04,0x04,0xC1,0x00,0x04,0x04,0xC1,0x00,0x04,0x04,0xC1,0x00,0x06,0x0C,0xC1,0x00,0x03,0xF8,0xC3,0x00,0x05,0xF0,0x62,0x00,0x06,0x00,0x7E,0x00,0x06,0x00,0x3C,0x00,0x00,0x00,0x00},/*"g",71*/
{0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x20,0x02,0x00,0x00,0x20,0x03,0xFF,0xFF,0xE0,0x07,0xFF,0xFF,0xE0,0x00,0x01,0x00,0x20,0x00,0x02,0x00,0x20,0x00,0x06,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x04,0x00,0x20,0x00,0x06,0x00,0x20,0x00,0x03,0xFF,0xE0,0x00,0x01,0xFF,0xE0,0x00,0x00,0x00,0x20,0x00,0x00,0x00,0x20},/*"h",72*/
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x20,0x00,0x04,0x00,0x20,0x00,0x04,0x00,0x20,0x00,0x04,0x00,0x20,0x03,0x87,0xFF,0xE0,0x03,0x8F,0xFF,0xE0,0x03,0x80,0x00,0x20,0x00,0x00,0x00,0x20,0x00,0x00,0x00,0x20,0x00,0x00,0x00,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"i",73*/
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x04,0x00,0x01,0x00,0x04,0x00,0x01,0x00,0x04,0x00,0x03,0x00,0x04,0x00,0x06,0x03,0x87,0xFF,0xFC,0x03,0x8F,0xFF,0xF8,0x03,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"j",74*/
{0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x20,0x02,0x00,0x00,0x20,0x03,0xFF,0xFF,0xE0,0x07,0xFF,0xFF,0xE0,0x00,0x00,0x08,0x20,0x00,0x00,0x10,0x20,0x00,0x00,0x30,0x00,0x00,0x00,0xFC,0x00,0x00,0x05,0x8E,0x00,0x00,0x07,0x07,0xA0,0x00,0x06,0x01,0xE0,0x00,0x04,0x00,0xE0,0x00,0x04,0x00,0x20,0x00,0x00,0x00,0x20,0x00,0x00,0x00,0x00},/*"k",75*/
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x20,0x02,0x00,0x00,0x20,0x02,0x00,0x00,0x20,0x02,0x00,0x00,0x20,0x03,0xFF,0xFF,0xE0,0x07,0xFF,0xFF,0xE0,0x00,0x00,0x00,0x20,0x00,0x00,0x00,0x20,0x00,0x00,0x00,0x20,0x00,0x00,0x00,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"l",76*/
{0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x20,0x00,0x07,0xFF,0xE0,0x00,0x0F,0xFF,0xE0,0x00,0x02,0x00,0x20,0x00,0x04,0x00,0x00,0x00,0x04,0x00,0x20,0x00,0x07,0xFF,0xE0,0x00,0x03,0xFF,0xE0,0x00,0x02,0x00,0x20,0x00,0x04,0x00,0x00,0x00,0x04,0x00,0x20,0x00,0x07,0xFF,0xE0,0x00,0x03,0xFF,0xE0,0x00,0x00,0x00,0x20,0x00,0x00,0x00,0x00},/*"m",77*/
{0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x20,0x00,0x04,0x00,0x20,0x00,0x07,0xFF,0xE0,0x00,0x0F,0xFF,0xE0,0x00,0x01,0x00,0x20,0x00,0x02,0x00,0x20,0x00,0x02,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x04,0x00,0x20,0x00,0x06,0x00,0x20,0x00,0x03,0xFF,0xE0,0x00,0x01,0xFF,0xE0,0x00,0x00,0x00,0x20,0x00,0x00,0x00,0x20},/*"n",78*/
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7E,0x00,0x00,0x00,0xFF,0x80,0x00,0x03,0x81,0xC0,0x00,0x02,0x00,0x40,0x00,0x06,0x00,0x20,0x00,0x04,0x00,0x20,0x00,0x04,0x00,0x20,0x00,0x04,0x00,0x20,0x00,0x06,0x00,0x20,0x00,0x02,0x00,0x40,0x00,0x03,0x81,0xC0,0x00,0x01,0xFF,0x80,0x00,0x00,0x7E,0x00,0x00,0x00,0x00,0x00},/*"o",79*/
{0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x01,0x00,0x04,0x00,0x01,0x00,0x07,0xFF,0xFF,0x00,0x0F,0xFF,0xFF,0x00,0x01,0x00,0xC1,0x00,0x02,0x00,0x41,0x00,0x04,0x00,0x20,0x00,0x04,0x00,0x20,0x00,0x04,0x00,0x20,0x00,0x04,0x00,0x20,0x00,0x06,0x00,0x40,0x00,0x03,0x01,0xC0,0x00,0x01,0xFF,0x80,0x00,0x00,0x7E,0x00,0x00,0x00,0x00,0x00},/*"p",80*/
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7E,0x00,0x00,0x01,0xFF,0x80,0x00,0x03,0x80,0xC0,0x00,0x02,0x00,0x60,0x00,0x04,0x00,0x20,0x00,0x04,0x00,0x20,0x00,0x04,0x00,0x20,0x00,0x04,0x00,0x20,0x00,0x02,0x00,0x41,0x00,0x03,0x00,0xC1,0x00,0x03,0xFF,0xFF,0x00,0x07,0xFF,0xFF,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x01},/*"q",81*/
{0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x20,0x00,0x04,0x00,0x20,0x00,0x04,0x00,0x20,0x00,0x04,0x00,0x20,0x00,0x0F,0xFF,0xE0,0x00,0x0F,0xFF,0xE0,0x00,0x00,0xC0,0x20,0x00,0x01,0x00,0x20,0x00,0x02,0x00,0x20,0x00,0x06,0x00,0x20,0x00,0x04,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x00,0x00,0x00},/*"r",82*/
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0xE0,0x00,0x01,0xC0,0xE0,0x00,0x03,0xE0,0x40,0x00,0x06,0x30,0x20,0x00,0x04,0x30,0x20,0x00,0x04,0x18,0x20,0x00,0x04,0x18,0x20,0x00,0x04,0x18,0x20,0x00,0x04,0x0C,0x20,0x00,0x02,0x0C,0x60,0x00,0x03,0x07,0xC0,0x00,0x07,0x83,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"s",83*/
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x0C,0x00,0x00,0x00,0x1F,0xFF,0x80,0x00,0xFF,0xFF,0xC0,0x00,0x04,0x00,0x60,0x00,0x04,0x00,0x20,0x00,0x04,0x00,0x20,0x00,0x04,0x00,0x20,0x00,0x04,0x00,0x40,0x00,0x00,0x01,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"t",84*/
{0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x07,0xFF,0x80,0x00,0x0F,0xFF,0xC0,0x00,0x00,0x00,0x60,0x00,0x00,0x00,0x20,0x00,0x00,0x00,0x20,0x00,0x00,0x00,0x20,0x00,0x00,0x00,0x20,0x00,0x04,0x00,0x40,0x00,0x04,0x00,0x80,0x00,0x07,0xFF,0xE0,0x00,0x0F,0xFF,0xC0,0x00,0x00,0x00,0x40,0x00,0x00,0x00,0x40},/*"u",85*/
{0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x07,0x80,0x00,0x00,0x07,0xF0,0x00,0x00,0x04,0xFE,0x00,0x00,0x04,0x1F,0xC0,0x00,0x00,0x03,0xE0,0x00,0x00,0x03,0x80,0x00,0x00,0x1C,0x00,0x00,0x04,0x60,0x00,0x00,0x07,0x80,0x00,0x00,0x06,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"v",86*/
{0x00,0x04,0x00,0x00,0x00,0x06,0x00,0x00,0x00,0x07,0xC0,0x00,0x00,0x07,0xFC,0x00,0x00,0x04,0x3F,0x80,0x00,0x00,0x03,0xE0,0x00,0x04,0x0F,0x80,0x00,0x06,0xF0,0x00,0x00,0x07,0xF0,0x00,0x00,0x07,0xFF,0x80,0x00,0x04,0x0F,0xE0,0x00,0x00,0x03,0x80,0x00,0x04,0x3C,0x00,0x00,0x07,0xC0,0x00,0x00,0x06,0x00,0x00,0x00,0x04,0x00,0x00},/*"w",87*/
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x00,0x04,0x00,0x20,0x00,0x04,0x00,0x60,0x00,0x07,0x00,0xE0,0x00,0x07,0x83,0x20,0x00,0x07,0xE6,0x00,0x00,0x04,0xF8,0x00,0x00,0x00,0x3C,0x00,0x00,0x04,0x5E,0x20,0x00,0x05,0x87,0xA0,0x00,0x06,0x01,0xE0,0x00,0x04,0x00,0x60,0x00,0x04,0x00,0x20,0x00,0x00,0x00,0x20,0x00,0x00,0x00,0x00},/*"x",88*/
{0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x04,0x00,0x03,0x00,0x07,0x00,0x03,0x00,0x07,0xE0,0x01,0x00,0x04,0xF8,0x01,0x00,0x04,0x1F,0x02,0x00,0x00,0x07,0xFC,0x00,0x00,0x00,0xE0,0x00,0x00,0x07,0x00,0x00,0x04,0x38,0x00,0x00,0x07,0xC0,0x00,0x00,0x06,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x00,0x00,0x00},/*"y",89*/
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x80,0x60,0x00,0x06,0x00,0xE0,0x00,0x04,0x03,0xE0,0x00,0x04,0x07,0xA0,0x00,0x04,0x0E,0x20,0x00,0x04,0x3C,0x20,0x00,0x04,0x70,0x20,0x00,0x05,0xE0,0x20,0x00,0x07,0x80,0x20,0x00,0x07,0x00,0x60,0x00,0x04,0x00,0xE0,0x00,0x00,0x03,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"z",90*/
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x00,0x00,0x00,0x80,0x00,0x00,0x01,0x40,0x00,0x07,0xFE,0x3F,0xF8,0x08,0x00,0x00,0x04,0x10,0x00,0x00,0x02,0x10,0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"{",91*/
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"|",92*/
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x00,0x00,0x02,0x10,0x00,0x00,0x02,0x08,0x00,0x00,0x04,0x07,0xFE,0x3F,0xF8,0x00,0x01,0x40,0x00,0x00,0x00,0x80,0x00,0x00,0x00,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"}",93*/
{0x00,0x00,0x00,0x00,0x18,0x00,0x00,0x00,0x30,0x00,0x00,0x00,0x40,0x00,0x00,0x00,0x40,0x00,0x00,0x00,0x40,0x00,0x00,0x00,0x20,0x00,0x00,0x00,0x30,0x00,0x00,0x00,0x08,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x0C,0x00,0x00,0x00,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"~",94*/
};
#endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,178 @@
/* Copyright 2018 Canaan Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* @file gpio.h
* @brief add from Canaan k210 SDK
* https://canaan-creative.com/developer
* @version 1.0
* @author AIIT XUOS Lab
* @date 2021-04-25
*/
#ifndef __GPIO_H__
#define __GPIO_H__
#include "platform.h"
#include <inttypes.h>
#include <stddef.h>
#include "gpio_common.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Structure for accessing GPIO registers by individual bit
*/
typedef struct _gpio_bits
{
uint32_t b0 : 1;
uint32_t b1 : 1;
uint32_t b2 : 1;
uint32_t b3 : 1;
uint32_t b4 : 1;
uint32_t b5 : 1;
uint32_t b6 : 1;
uint32_t b7 : 1;
uint32_t b8 : 1;
uint32_t b9 : 1;
uint32_t b10 : 1;
uint32_t b11 : 1;
uint32_t b12 : 1;
uint32_t b13 : 1;
uint32_t b14 : 1;
uint32_t b15 : 1;
uint32_t b16 : 1;
uint32_t b17 : 1;
uint32_t b18 : 1;
uint32_t b19 : 1;
uint32_t b20 : 1;
uint32_t b21 : 1;
uint32_t b22 : 1;
uint32_t b23 : 1;
uint32_t b24 : 1;
uint32_t b25 : 1;
uint32_t b26 : 1;
uint32_t b27 : 1;
uint32_t b28 : 1;
uint32_t b29 : 1;
uint32_t b30 : 1;
uint32_t b31 : 1;
} __attribute__((packed, aligned(4))) gpio_bits_t;
/**
* @brief Structure of templates for accessing GPIO registers
*/
typedef union _gpio_access_tp
{
/* 32x1 bit mode */
uint32_t u32[1];
/* 16x2 bit mode */
uint16_t u16[2];
/* 8x4 bit mode */
uint8_t u8[4];
/* 1 bit mode */
gpio_bits_t bits;
} __attribute__((packed, aligned(4))) gpio_access_tp_t;
/**
* @brief The GPIO address map
*/
typedef struct _gpio
{
/* Offset 0x00: Data (output) registers */
gpio_access_tp_t data_output;
/* Offset 0x04: Data direction registers */
gpio_access_tp_t direction;
/* Offset 0x08: Data source registers */
gpio_access_tp_t source;
/* Offset 0x10 - 0x2f: Unused registers, 9x4 bytes */
uint32_t unused_0[9];
/* Offset 0x30: Interrupt enable/disable registers */
gpio_access_tp_t interrupt_enable;
/* Offset 0x34: Interrupt mask registers */
gpio_access_tp_t interrupt_mask;
/* Offset 0x38: Interrupt level registers */
gpio_access_tp_t interrupt_level;
/* Offset 0x3c: Interrupt polarity registers */
gpio_access_tp_t interrupt_polarity;
/* Offset 0x40: Interrupt status registers */
gpio_access_tp_t interrupt_status;
/* Offset 0x44: Raw interrupt status registers */
gpio_access_tp_t interrupt_status_raw;
/* Offset 0x48: Interrupt debounce registers */
gpio_access_tp_t interrupt_debounce;
/* Offset 0x4c: Registers for clearing interrupts */
gpio_access_tp_t interrupt_clear;
/* Offset 0x50: External port (data input) registers */
gpio_access_tp_t data_input;
/* Offset 0x54 - 0x5f: Unused registers, 3x4 bytes */
uint32_t unused_1[3];
/* Offset 0x60: Sync level registers */
gpio_access_tp_t sync_level;
/* Offset 0x64: ID code */
gpio_access_tp_t id_code;
/* Offset 0x68: Interrupt both edge type */
gpio_access_tp_t interrupt_bothedge;
} __attribute__((packed, aligned(4))) gpio_t;
/**
* @brief Bus GPIO object instance
*/
extern volatile gpio_t *const gpio;
/**
* @brief Gpio initialize
*
* @return Result
* - 0 Success
* - Other Fail
*/
int gpio_init(void);
/**
* @brief Set Gpio drive mode
*
* @param[in] pin Gpio pin
* @param[in] mode Gpio pin drive mode
*/
void gpio_set_drive_mode(uint8_t pin, gpio_drive_mode_t mode);
/**
* @brief Get Gpio pin value
*
* @param[in] pin Gpio pin
* @return Pin value
*
* - GPIO_PV_Low Gpio pin low
* - GPIO_PV_High Gpio pin high
*/
gpio_pin_value_t gpio_get_pin(uint8_t pin);
/**
* @brief Set Gpio pin value
*
* @param[in] pin Gpio pin
* @param[in] value Gpio pin value
*/
void gpio_set_pin(uint8_t pin, gpio_pin_value_t value);
#ifdef __cplusplus
}
#endif
#endif /* __GPIO_H__ */

View File

@ -0,0 +1,61 @@
/* Copyright 2018 Canaan Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* @file gpio_common.h
* @brief add from Canaan k210 SDK
* https://canaan-creative.com/developer
* @version 1.0
* @author AIIT XUOS Lab
* @date 2021-04-25
*/
#ifndef __GPIO_COMMON_H__
#define __GPIO_COMMON_H__
#ifdef __cplusplus
extern "C" {
#endif
typedef enum _gpio_drive_mode
{
GPIO_DM_INPUT,
GPIO_DM_INPUT_PULL_DOWN,
GPIO_DM_INPUT_PULL_UP,
GPIO_DM_OUTPUT,
} gpio_drive_mode_t;
typedef enum _gpio_pin_edge
{
GPIO_PE_NONE,
GPIO_PE_FALLING,
GPIO_PE_RISING,
GPIO_PE_BOTH,
GPIO_PE_LOW,
GPIO_PE_HIGH = 8,
} GpioPinEdgeT;
typedef enum _gpio_pin_value
{
GPIO_PV_LOW,
GPIO_PV_HIGH
} gpio_pin_value_t;
#ifdef __cplusplus
}
#endif
#endif /* __GPIO_COMMON_H__ */

View File

@ -0,0 +1,277 @@
/* Copyright 2018 Canaan Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* @file gpiohs.h
* @brief add from Canaan k210 SDK
* https://canaan-creative.com/developer
* @version 1.0
* @author AIIT XUOS Lab
* @date 2021-04-25
*/
#ifndef __GPIOHS_H__
#define __GPIOHS_H__
#include <stdint.h>
#include "platform.h"
#include <stddef.h>
#include "gpio_common.h"
#include "plic.h"
#ifdef __cplusplus
extern "C" {
#endif
/* clang-format off */
/* Register address offsets */
#define GPIOHS_INPUT_VAL (0x00)
#define GPIOHS_INPUT_EN (0x04)
#define GPIOHS_OUTPUT_EN (0x08)
#define GPIOHS_OUTPUT_VAL (0x0C)
#define GPIOHS_PULLUP_EN (0x10)
#define GPIOHS_DRIVE (0x14)
#define GPIOHS_RISE_IE (0x18)
#define GPIOHS_RISE_IP (0x1C)
#define GPIOHS_FALL_IE (0x20)
#define GPIOHS_FALL_IP (0x24)
#define GPIOHS_HIGH_IE (0x28)
#define GPIOHS_HIGH_IP (0x2C)
#define GPIOHS_LOW_IE (0x30)
#define GPIOHS_LOW_IP (0x34)
#define GPIOHS_IOF_EN (0x38)
#define GPIOHS_IOF_SEL (0x3C)
#define GPIOHS_OUTPUT_XOR (0x40)
/* clang-format on */
/**
* @brief GPIO bits raw object
*/
typedef struct _gpiohs_raw
{
/* Address offset 0x00 */
uint32_t input_val;
/* Address offset 0x04 */
uint32_t input_en;
/* Address offset 0x08 */
uint32_t output_en;
/* Address offset 0x0c */
uint32_t output_val;
/* Address offset 0x10 */
uint32_t pullup_en;
/* Address offset 0x14 */
uint32_t drive;
/* Address offset 0x18 */
uint32_t rise_ie;
/* Address offset 0x1c */
uint32_t rise_ip;
/* Address offset 0x20 */
uint32_t fall_ie;
/* Address offset 0x24 */
uint32_t fall_ip;
/* Address offset 0x28 */
uint32_t high_ie;
/* Address offset 0x2c */
uint32_t high_ip;
/* Address offset 0x30 */
uint32_t low_ie;
/* Address offset 0x34 */
uint32_t low_ip;
/* Address offset 0x38 */
uint32_t iof_en;
/* Address offset 0x3c */
uint32_t iof_sel;
/* Address offset 0x40 */
uint32_t output_xor;
} __attribute__((packed, aligned(4))) gpiohs_raw_t;
/**
* @brief GPIO bits object
*/
typedef struct _gpiohs_bits
{
uint32_t b0 : 1;
uint32_t b1 : 1;
uint32_t b2 : 1;
uint32_t b3 : 1;
uint32_t b4 : 1;
uint32_t b5 : 1;
uint32_t b6 : 1;
uint32_t b7 : 1;
uint32_t b8 : 1;
uint32_t b9 : 1;
uint32_t b10 : 1;
uint32_t b11 : 1;
uint32_t b12 : 1;
uint32_t b13 : 1;
uint32_t b14 : 1;
uint32_t b15 : 1;
uint32_t b16 : 1;
uint32_t b17 : 1;
uint32_t b18 : 1;
uint32_t b19 : 1;
uint32_t b20 : 1;
uint32_t b21 : 1;
uint32_t b22 : 1;
uint32_t b23 : 1;
uint32_t b24 : 1;
uint32_t b25 : 1;
uint32_t b26 : 1;
uint32_t b27 : 1;
uint32_t b28 : 1;
uint32_t b29 : 1;
uint32_t b30 : 1;
uint32_t b31 : 1;
} __attribute__((packed, aligned(4))) gpiohs_bits_t;
/**
* @brief GPIO bits multi access union
*/
typedef union _gpiohs_u32
{
/* 32x1 bit mode */
uint32_t u32[1];
/* 16x2 bit mode */
uint16_t u16[2];
/* 8x4 bit mode */
uint8_t u8[4];
/* 1 bit mode */
gpiohs_bits_t bits;
} __attribute__((packed, aligned(4))) gpiohs_u32_t;
/**
* @brief GPIO object
*
* The GPIO controller is a peripheral device mapped in the
* internal memory map, discoverable in the Configuration String.
* It is responsible for low-level configuration of the actual
* GPIO pads on the device (direction, pull up-enable, and drive
* value), as well as selecting between various sources of the
* controls for these signals. The GPIO controller allows seperate
* configuration of each of N GPIO bits.
*
* Once the interrupt is pending, it will remain set until a 1 is
* written to the *_ip register at that bit.
*/
typedef struct _gpiohs
{
/* Address offset 0x00, Input Values */
gpiohs_u32_t input_val;
/* Address offset 0x04, Input enable */
gpiohs_u32_t input_en;
/* Address offset 0x08, Output enable */
gpiohs_u32_t output_en;
/* Address offset 0x0c, Onput Values */
gpiohs_u32_t output_val;
/* Address offset 0x10, Internal Pull-Ups enable */
gpiohs_u32_t pullup_en;
/* Address offset 0x14, Drive Strength */
gpiohs_u32_t drive;
/* Address offset 0x18, Rise interrupt enable */
gpiohs_u32_t rise_ie;
/* Address offset 0x1c, Rise interrupt pending */
gpiohs_u32_t rise_ip;
/* Address offset 0x20, Fall interrupt enable */
gpiohs_u32_t fall_ie;
/* Address offset 0x24, Fall interrupt pending */
gpiohs_u32_t fall_ip;
/* Address offset 0x28, High interrupt enable */
gpiohs_u32_t high_ie;
/* Address offset 0x2c, High interrupt pending */
gpiohs_u32_t high_ip;
/* Address offset 0x30, Low interrupt enable */
gpiohs_u32_t low_ie;
/* Address offset 0x34, Low interrupt pending */
gpiohs_u32_t low_ip;
/* Address offset 0x38, HW I/O Function enable */
gpiohs_u32_t iof_en;
/* Address offset 0x3c, HW I/O Function select */
gpiohs_u32_t iof_sel;
/* Address offset 0x40, Output XOR (invert) */
gpiohs_u32_t output_xor;
} __attribute__((packed, aligned(4))) gpiohs_t;
/**
* @brief GPIO High-speed object instanse
*/
extern volatile gpiohs_t *const gpiohs;
/**
* @brief Set Gpiohs drive mode
*
* @param[in] pin Gpiohs pin
* @param[in] mode Gpiohs pin drive mode
*/
void gpiohs_set_drive_mode(uint8_t pin, gpio_drive_mode_t mode);
/**
* @brief Get Gpiohs pin value
*
* @param[in] pin Gpiohs pin
* @return Pin value
*
* - GPIO_PV_Low Gpiohs pin low
* - GPIO_PV_High Gpiohs pin high
*/
gpio_pin_value_t gpiohs_get_pin(uint8_t pin);
/**
* @brief Set Gpiohs pin value
*
* @param[in] pin Gpiohs pin
* @param[in] value Gpiohs pin value
*/
void gpiohs_set_pin(uint8_t pin, gpio_pin_value_t value);
/**
* @brief Set Gpiohs pin edge for interrupt
*
* @param[in] pin Gpiohs pin
* @param[in] edge Gpiohs pin edge type
*/
void gpiohs_set_pin_edge(uint8_t pin, GpioPinEdgeT edge);
/**
* @brief Set Gpiohs pin interrupt
*
* @param[in] pin Gpiohs pin
* @param[in] priority Gpiohs pin interrupt priority
* @param[in] func Gpiohs pin interrupt service routine
*/
void gpiohs_set_irq(uint8_t pin, uint32_t priority, void(*func)());
/**
* @brief Set Gpiohs pin interrupt
*
* @param[in] pin Gpiohs pin
* @param[in] priority Gpiohs pin interrupt priority
* @param[in] callback Gpiohs pin interrupt service routine
* @param[in] ctx Gpiohs interrupt param
*/
void gpiohs_irq_register(uint8_t pin, uint32_t priority, plic_irq_callback_t callback, void *ctx);
/**
* @brief Unregister Gpiohs pin interrupt
*
* @param[in] pin Gpiohs pin
*/
void gpiohs_irq_unregister(uint8_t pin);
#ifdef __cplusplus
}
#endif
#endif /* __GPIOHS_H__ */

View File

@ -0,0 +1,171 @@
/* Copyright 2018 Canaan Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* @file hardware_hwtimer.h
* @brief add from Canaan k210 SDK
* https://canaan-creative.com/developer
* @version 1.0
* @author AIIT XUOS Lab
* @date 2021-04-25
*/
#ifndef __HARDWARE_HWTIMER_H__
#define __HARDWARE_HWTIMER_H__
#include <stdint.h>
#include <stddef.h>
#ifdef __cplusplus
extern "C" {
#endif
/* clang-format off */
typedef struct _timer_channel
{
/* TIMER_N Load Count Register (0x00+(N-1)*0x14) */
volatile uint32_t load_count;
/* TIMER_N Current Value Register (0x04+(N-1)*0x14) */
volatile uint32_t current_value;
/* TIMER_N Control Register (0x08+(N-1)*0x14) */
volatile uint32_t control;
/* TIMER_N Interrupt Clear Register (0x0c+(N-1)*0x14) */
volatile uint32_t eoi;
/* TIMER_N Interrupt Status Register (0x10+(N-1)*0x14) */
volatile uint32_t intr_stat;
} __attribute__((packed, aligned(4))) timer_channel_t;
typedef struct _kendryte_timer
{
/* TIMER_N Register (0x00-0x4c) */
volatile timer_channel_t channel[4];
/* reserverd (0x50-0x9c) */
volatile uint32_t resv1[20];
/* TIMER Interrupt Status Register (0xa0) */
volatile uint32_t intr_stat;
/* TIMER Interrupt Clear Register (0xa4) */
volatile uint32_t eoi;
/* TIMER Raw Interrupt Status Register (0xa8) */
volatile uint32_t raw_intr_stat;
/* TIMER Component Version Register (0xac) */
volatile uint32_t comp_version;
/* TIMER_N Load Count2 Register (0xb0-0xbc) */
volatile uint32_t load_count2[4];
} __attribute__((packed, aligned(4))) kendryte_timer_t;
typedef enum _timer_deivce_number
{
TIMER_DEVICE_0,
TIMER_DEVICE_1,
TIMER_DEVICE_2,
TIMER_DEVICE_MAX,
} timer_device_number_t;
typedef enum _timer_channel_number
{
TIMER_CHANNEL_0,
TIMER_CHANNEL_1,
TIMER_CHANNEL_2,
TIMER_CHANNEL_3,
TIMER_CHANNEL_MAX,
} timer_channel_number_t;
/* TIMER Control Register */
#define TIMER_CR_ENABLE 0x00000001
#define TIMER_CR_MODE_MASK 0x00000002
#define TIMER_CR_FREE_MODE 0x00000000
#define TIMER_CR_USER_MODE 0x00000002
#define TIMER_CR_INTERRUPT_MASK 0x00000004
#define TIMER_CR_PWM_ENABLE 0x00000008
/* clang-format on */
extern volatile kendryte_timer_t *const timer[3];
/**
* @brief Definitions for the timer callbacks
*/
typedef int (*timer_callback_t)(void *ctx);
/**
* @brief Set timer timeout
*
* @param[in] timer timer
* @param[in] channel channel
* @param[in] nanoseconds timeout
*
* @return the real timeout
*/
size_t timer_set_interval(timer_device_number_t timer_number, timer_channel_number_t channel, size_t nanoseconds);
/**
* @brief Init timer
*
* @param[in] timer timer
*/
void timer_init(timer_device_number_t timer_number);
/**
* @brief [DEPRECATED] Set timer timeout function
*
* @param[in] timer timer
* @param[in] channel channel
* @param[in] func timeout function
* @param[in] priority interrupt priority
*
*/
void timer_set_irq(timer_device_number_t timer_number, timer_channel_number_t channel, void(*func)(), uint32_t priority);
/**
* @brief Register timer interrupt user callback function
*
* @param[in] device The timer device number
* @param[in] channel The channel
* @param[in] is_one_shot Indicates if single shot
* @param[in] priority The priority
* @param[in] callback The callback function
* @param[in] ctx The context
*
* @return result
* - 0 Success
* - Other Fail
*/
int timer_irq_register(timer_device_number_t device, timer_channel_number_t channel, int is_single_shot, uint32_t priority, timer_callback_t callback, void *ctx);
/**
* @brief Deregister timer interrupt user callback function
*
* @param[in] device The timer device number
* @param[in] channel The channel
*
* @return result
* - 0 Success
* - Other Fail
*/
int timer_irq_unregister(timer_device_number_t device, timer_channel_number_t channel);
/**
* @brief Enable timer
*
* @param[in] timer timer
* @param[in] channel channel
* @param[in] enable Enable or disable
*
*/
void timer_set_enable(timer_device_number_t timer_number, timer_channel_number_t channel, uint32_t enable);
#ifdef __cplusplus
}
#endif
#endif /* __TIMER_H__ */

View File

@ -0,0 +1,482 @@
/* Copyright 2018 Canaan Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* @file hardware_i2c.h
* @brief add from Canaan k210 SDK
* https://canaan-creative.com/developer
* @version 1.0
* @author AIIT XUOS Lab
* @date 2021-04-25
*/
#ifndef __HARDWARE_I2C_H__
#define __HARDWARE_I2C_H__
#include <stdint.h>
#include <stddef.h>
#include "dmac.h"
#ifdef __cplusplus
extern "C" {
#endif
#define I2C_MAX_NUM 3
/* clang-format off */
typedef struct _i2c
{
/* I2C Control Register (0x00) */
volatile uint32_t con;
/* I2C Target Address Register (0x04) */
volatile uint32_t tar;
/* I2C Slave Address Register (0x08) */
volatile uint32_t sar;
/* reserved (0x0c) */
volatile uint32_t resv1;
/* I2C Data Buffer and Command Register (0x10) */
volatile uint32_t data_cmd;
/* I2C Standard Speed Clock SCL High Count Register (0x14) */
volatile uint32_t ss_scl_hcnt;
/* I2C Standard Speed Clock SCL Low Count Register (0x18) */
volatile uint32_t ss_scl_lcnt;
/* reserverd (0x1c-0x28) */
volatile uint32_t resv2[4];
/* I2C Interrupt Status Register (0x2c) */
volatile uint32_t intr_stat;
/* I2C Interrupt Mask Register (0x30) */
volatile uint32_t intr_mask;
/* I2C Raw Interrupt Status Register (0x34) */
volatile uint32_t raw_intr_stat;
/* I2C Receive FIFO Threshold Register (0x38) */
volatile uint32_t rx_tl;
/* I2C Transmit FIFO Threshold Register (0x3c) */
volatile uint32_t tx_tl;
/* I2C Clear Combined and Individual Interrupt Register (0x40) */
volatile uint32_t clr_intr;
/* I2C Clear RX_UNDER Interrupt Register (0x44) */
volatile uint32_t clr_rx_under;
/* I2C Clear RX_OVER Interrupt Register (0x48) */
volatile uint32_t clr_rx_over;
/* I2C Clear TX_OVER Interrupt Register (0x4c) */
volatile uint32_t clr_tx_over;
/* I2C Clear RD_REQ Interrupt Register (0x50) */
volatile uint32_t clr_rd_req;
/* I2C Clear TX_ABRT Interrupt Register (0x54) */
volatile uint32_t clr_tx_abrt;
/* I2C Clear RX_DONE Interrupt Register (0x58) */
volatile uint32_t clr_rx_done;
/* I2C Clear ACTIVITY Interrupt Register (0x5c) */
volatile uint32_t clr_activity;
/* I2C Clear STOP_DET Interrupt Register (0x60) */
volatile uint32_t clr_stop_det;
/* I2C Clear START_DET Interrupt Register (0x64) */
volatile uint32_t clr_start_det;
/* I2C Clear GEN_CALL Interrupt Register (0x68) */
volatile uint32_t clr_gen_call;
/* I2C Enable Register (0x6c) */
volatile uint32_t enable;
/* I2C Status Register (0x70) */
volatile uint32_t status;
/* I2C Transmit FIFO Level Register (0x74) */
volatile uint32_t txflr;
/* I2C Receive FIFO Level Register (0x78) */
volatile uint32_t rxflr;
/* I2C SDA Hold Time Length Register (0x7c) */
volatile uint32_t sda_hold;
/* I2C Transmit Abort Source Register (0x80) */
volatile uint32_t tx_abrt_source;
/* reserved (0x84) */
volatile uint32_t resv3;
/* I2C DMA Control Register (0x88) */
volatile uint32_t dma_cr;
/* I2C DMA Transmit Data Level Register (0x8c) */
volatile uint32_t dma_tdlr;
/* I2C DMA Receive Data Level Register (0x90) */
volatile uint32_t dma_rdlr;
/* I2C SDA Setup Register (0x94) */
volatile uint32_t sda_setup;
/* I2C ACK General Call Register (0x98) */
volatile uint32_t general_call;
/* I2C Enable Status Register (0x9c) */
volatile uint32_t enable_status;
/* I2C SS, FS or FM+ spike suppression limit (0xa0) */
volatile uint32_t fs_spklen;
/* reserved (0xa4-0xf0) */
volatile uint32_t resv4[20];
/* I2C Component Parameter Register 1 (0xf4) */
volatile uint32_t comp_param_1;
/* I2C Component Version Register (0xf8) */
volatile uint32_t comp_version;
/* I2C Component Type Register (0xfc) */
volatile uint32_t comp_type;
} __attribute__((packed, aligned(4))) i2c_t;
/* I2C Control Register*/
#define I2C_CON_MASTER_MODE 0x00000001U
#define I2C_CON_SPEED_MASK 0x00000006U
#define I2C_CON_SPEED(x) ((x) << 1)
#define I2C_CON_10BITADDR_SLAVE 0x00000008U
#define I2C_CON_RESTART_EN 0x00000020U
#define I2C_CON_SLAVE_DISABLE 0x00000040U
#define I2C_CON_STOP_DET_IFADDRESSED 0x00000080U
#define I2C_CON_TX_EMPTY_CTRL 0x00000100U
/* I2C Target Address Register*/
#define I2C_TAR_ADDRESS_MASK 0x000003FFU
#define I2C_TAR_ADDRESS(x) ((x) << 0)
#define I2C_TAR_GC_OR_START 0x00000400U
#define I2C_TAR_SPECIAL 0x00000800U
#define I2C_TAR_10BITADDR_MASTER 0x00001000U
/* I2C Slave Address Register*/
#define I2C_SAR_ADDRESS_MASK 0x000003FFU
#define I2C_SAR_ADDRESS(x) ((x) << 0)
/* I2C Rx/Tx Data Buffer and Command Register*/
#define I2C_DATA_CMD_CMD 0x00000100U
#define I2C_DATA_CMD_DATA_MASK 0x000000FFU
#define I2C_DATA_CMD_DATA(x) ((x) << 0)
/* Standard Speed I2C Clock SCL High Count Register*/
#define I2C_SS_SCL_HCNT_COUNT_MASK 0x0000FFFFU
#define I2C_SS_SCL_HCNT_COUNT(x) ((x) << 0)
/* Standard Speed I2C Clock SCL Low Count Register*/
#define I2C_SS_SCL_LCNT_COUNT_MASK 0x0000FFFFU
#define I2C_SS_SCL_LCNT_COUNT(x) ((x) << 0)
/* I2C Interrupt Status Register*/
#define I2C_INTR_STAT_RX_UNDER 0x00000001U
#define I2C_INTR_STAT_RX_OVER 0x00000002U
#define I2C_INTR_STAT_RX_FULL 0x00000004U
#define I2C_INTR_STAT_TX_OVER 0x00000008U
#define I2C_INTR_STAT_TX_EMPTY 0x00000010U
#define I2C_INTR_STAT_RD_REQ 0x00000020U
#define I2C_INTR_STAT_TX_ABRT 0x00000040U
#define I2C_INTR_STAT_RX_DONE 0x00000080U
#define I2C_INTR_STAT_ACTIVITY 0x00000100U
#define I2C_INTR_STAT_STOP_DET 0x00000200U
#define I2C_INTR_STAT_START_DET 0x00000400U
#define I2C_INTR_STAT_GEN_CALL 0x00000800U
/* I2C Interrupt Mask Register*/
#define I2C_INTR_MASK_RX_UNDER 0x00000001U
#define I2C_INTR_MASK_RX_OVER 0x00000002U
#define I2C_INTR_MASK_RX_FULL 0x00000004U
#define I2C_INTR_MASK_TX_OVER 0x00000008U
#define I2C_INTR_MASK_TX_EMPTY 0x00000010U
#define I2C_INTR_MASK_RD_REQ 0x00000020U
#define I2C_INTR_MASK_TX_ABRT 0x00000040U
#define I2C_INTR_MASK_RX_DONE 0x00000080U
#define I2C_INTR_MASK_ACTIVITY 0x00000100U
#define I2C_INTR_MASK_STOP_DET 0x00000200U
#define I2C_INTR_MASK_START_DET 0x00000400U
#define I2C_INTR_MASK_GEN_CALL 0x00000800U
/* I2C Raw Interrupt Status Register*/
#define I2C_RAW_INTR_MASK_RX_UNDER 0x00000001U
#define I2C_RAW_INTR_MASK_RX_OVER 0x00000002U
#define I2C_RAW_INTR_MASK_RX_FULL 0x00000004U
#define I2C_RAW_INTR_MASK_TX_OVER 0x00000008U
#define I2C_RAW_INTR_MASK_TX_EMPTY 0x00000010U
#define I2C_RAW_INTR_MASK_RD_REQ 0x00000020U
#define I2C_RAW_INTR_MASK_TX_ABRT 0x00000040U
#define I2C_RAW_INTR_MASK_RX_DONE 0x00000080U
#define I2C_RAW_INTR_MASK_ACTIVITY 0x00000100U
#define I2C_RAW_INTR_MASK_STOP_DET 0x00000200U
#define I2C_RAW_INTR_MASK_START_DET 0x00000400U
#define I2C_RAW_INTR_MASK_GEN_CALL 0x00000800U
/* I2C Receive FIFO Threshold Register*/
#define I2C_RX_TL_VALUE_MASK 0x00000007U
#define I2C_RX_TL_VALUE(x) ((x) << 0)
/* I2C Transmit FIFO Threshold Register*/
#define I2C_TX_TL_VALUE_MASK 0x00000007U
#define I2C_TX_TL_VALUE(x) ((x) << 0)
/* Clear Combined and Individual Interrupt Register*/
#define I2C_CLR_INTR_CLR 0x00000001U
/* Clear RX_UNDER Interrupt Register*/
#define I2C_CLR_RX_UNDER_CLR 0x00000001U
/* Clear RX_OVER Interrupt Register*/
#define I2C_CLR_RX_OVER_CLR 0x00000001U
/* Clear TX_OVER Interrupt Register*/
#define I2C_CLR_TX_OVER_CLR 0x00000001U
/* Clear RD_REQ Interrupt Register*/
#define I2C_CLR_RD_REQ_CLR 0x00000001U
/* Clear TX_ABRT Interrupt Register*/
#define I2C_CLR_TX_ABRT_CLR 0x00000001U
/* Clear RX_DONE Interrupt Register*/
#define I2C_CLR_RX_DONE_CLR 0x00000001U
/* Clear ACTIVITY Interrupt Register*/
#define I2C_CLR_ACTIVITY_CLR 0x00000001U
/* Clear STOP_DET Interrupt Register*/
#define I2C_CLR_STOP_DET_CLR 0x00000001U
/* Clear START_DET Interrupt Register*/
#define I2C_CLR_START_DET_CLR 0x00000001U
/* Clear GEN_CALL Interrupt Register*/
#define I2C_CLR_GEN_CALL_CLR 0x00000001U
/* I2C Enable Register*/
#define I2C_ENABLE_ENABLE 0x00000001U
#define I2C_ENABLE_ABORT 0x00000002U
#define I2C_ENABLE_TX_CMD_BLOCK 0x00000004U
/* I2C Status Register*/
#define I2C_STATUS_ACTIVITY 0x00000001U
#define I2C_STATUS_TFNF 0x00000002U
#define I2C_STATUS_TFE 0x00000004U
#define I2C_STATUS_RFNE 0x00000008U
#define I2C_STATUS_RFF 0x00000010U
#define I2C_STATUS_MST_ACTIVITY 0x00000020U
#define I2C_STATUS_SLV_ACTIVITY 0x00000040U
/* I2C Transmit FIFO Level Register*/
#define I2C_TXFLR_VALUE_MASK 0x00000007U
#define I2C_TXFLR_VALUE(x) ((x) << 0)
/* I2C Receive FIFO Level Register*/
#define I2C_RXFLR_VALUE_MASK 0x00000007U
#define I2C_RXFLR_VALUE(x) ((x) << 0)
/* I2C SDA Hold Time Length Register*/
#define I2C_SDA_HOLD_TX_MASK 0x0000FFFFU
#define I2C_SDA_HOLD_TX(x) ((x) << 0)
#define I2C_SDA_HOLD_RX_MASK 0x00FF0000U
#define I2C_SDA_HOLD_RX(x) ((x) << 16)
/* I2C Transmit Abort Source Register*/
#define I2C_TX_ABRT_SOURCE_7B_ADDR_NOACK 0x00000001U
#define I2C_TX_ABRT_SOURCE_10B_ADDR1_NOACK 0x00000002U
#define I2C_TX_ABRT_SOURCE_10B_ADDR2_NOACK 0x00000004U
#define I2C_TX_ABRT_SOURCE_TXDATA_NOACK 0x00000008U
#define I2C_TX_ABRT_SOURCE_GCALL_NOACK 0x00000010U
#define I2C_TX_ABRT_SOURCE_GCALL_READ 0x00000020U
#define I2C_TX_ABRT_SOURCE_HS_ACKDET 0x00000040U
#define I2C_TX_ABRT_SOURCE_SBYTE_ACKDET 0x00000080U
#define I2C_TX_ABRT_SOURCE_HS_NORSTRT 0x00000100U
#define I2C_TX_ABRT_SOURCE_SBYTE_NORSTRT 0x00000200U
#define I2C_TX_ABRT_SOURCE_10B_RD_NORSTRT 0x00000400U
#define I2C_TX_ABRT_SOURCE_MASTER_DIS 0x00000800U
#define I2C_TX_ABRT_SOURCE_MST_ARBLOST 0x00001000U
#define I2C_TX_ABRT_SOURCE_SLVFLUSH_TXFIFO 0x00002000U
#define I2C_TX_ABRT_SOURCE_SLV_ARBLOST 0x00004000U
#define I2C_TX_ABRT_SOURCE_SLVRD_INTX 0x00008000U
#define I2C_TX_ABRT_SOURCE_USER_ABRT 0x00010000U
/* DMA Control Register*/
#define I2C_DMA_CR_RDMAE 0x00000001U
#define I2C_DMA_CR_TDMAE 0x00000002U
/* DMA Transmit Data Level Register*/
#define I2C_DMA_TDLR_VALUE_MASK 0x00000007U
#define I2C_DMA_TDLR_VALUE(x) ((x) << 0)
/* DMA Receive Data Level Register*/
#define I2C_DMA_RDLR_VALUE_MASK 0x00000007U
#define I2C_DMA_RDLR_VALUE(x) ((x) << 0)
/* I2C SDA Setup Register*/
#define I2C_SDA_SETUP_VALUE_MASK 0x000000FFU
#define I2C_SDA_SETUP_VALUE(x) ((x) << 0)
/* I2C ACK General Call Register*/
#define I2C_ACK_GENERAL_CALL_ENABLE 0x00000001U
/* I2C Enable Status Register*/
#define I2C_ENABLE_STATUS_IC_ENABLE 0x00000001U
#define I2C_ENABLE_STATUS_SLV_DIS_BUSY 0x00000002U
#define I2C_ENABLE_STATUS_SLV_RX_DATA_LOST 0x00000004U
/* I2C SS, FS or FM+ spike suppression limit*/
#define I2C_FS_SPKLEN_VALUE_MASK 0x000000FFU
#define I2C_FS_SPKLEN_VALUE(x) ((x) << 0)
/* Component Parameter Register 1*/
#define I2C_COMP_PARAM1_APB_DATA_WIDTH 0x00000003U
#define I2C_COMP_PARAM1_MAX_SPEED_MODE 0x0000000CU
#define I2C_COMP_PARAM1_HC_COUNT_VALUES 0x00000010U
#define I2C_COMP_PARAM1_INTR_IO 0x00000020U
#define I2C_COMP_PARAM1_HAS_DMA 0x00000040U
#define I2C_COMP_PARAM1_ENCODED_PARAMS 0x00000080U
#define I2C_COMP_PARAM1_RX_BUFFER_DEPTH 0x0000FF00U
#define I2C_COMP_PARAM1_TX_BUFFER_DEPTH 0x00FF0000U
/* I2C Component Version Register*/
#define I2C_COMP_VERSION_VALUE 0xFFFFFFFFU
/* I2C Component Type Register*/
#define I2C_COMP_TYPE_VALUE 0xFFFFFFFFU
/* clang-format on */
extern volatile i2c_t *const i2c[3];
typedef enum _i2c_device_number
{
I2C_DEVICE_0,
I2C_DEVICE_1,
I2C_DEVICE_2,
I2C_DEVICE_MAX,
} i2c_device_number_t;
typedef enum _i2c_bus_speed_mode
{
I2C_BS_STANDARD,
I2C_BS_FAST,
I2C_BS_HIGHSPEED
} i2c_bus_speed_mode_t;
typedef enum _i2c_event
{
I2C_EV_START,
I2C_EV_RESTART,
I2C_EV_STOP
} i2c_event_id_t;
typedef struct _i2c_slave_handler
{
void(*on_receive)(uint32_t data);
uint32_t(*on_transmit)();
void(*on_event)(i2c_event_id_t event);
} i2c_slave_handler_t;
typedef enum _i2c_transfer_mode
{
I2C_SEND,
I2C_RECEIVE,
} i2c_transfer_mode_t;
typedef struct _i2c_data_t
{
dmac_channel_number_t tx_channel;
dmac_channel_number_t rx_channel;
uint32_t *tx_buf;
size_t tx_len;
uint32_t *rx_buf;
size_t rx_len;
i2c_transfer_mode_t TransferMode;
} i2c_data_t;
/**
* @brief Set i2c params
*
* @param[in] i2c_num i2c number
* @param[in] slave_address i2c slave device address
* @param[in] address_width address width 7bit or 10bit
* @param[in] i2c_clk i2c clk rate
*/
void i2c_init(i2c_device_number_t i2c_num, uint32_t slave_address, uint32_t address_width,
uint32_t i2c_clk);
/**
* @brief I2c send data
*
* @param[in] i2c_num i2c number
* @param[in] SendBuf send data
* @param[in] send_buf_len send data length
*
* @return result
* - 0 Success
* - Other Fail
*/
int i2c_send_data(i2c_device_number_t i2c_num, const uint8_t *SendBuf, size_t send_buf_len);
/**
* @brief Init i2c as slave mode.
*
* @param[in] i2c_num i2c number
* @param[in] slave_address i2c slave device address
* @param[in] address_width address width 7bit or 10bit
* @param[in] handler Handle of i2c slave interrupt function.
*/
void i2c_init_as_slave(i2c_device_number_t i2c_num, uint32_t slave_address, uint32_t address_width,
const i2c_slave_handler_t *handler);
/**
* @brief I2c send data by dma
*
* @param[in] dma_channel_num dma channel
* @param[in] i2c_num i2c number
* @param[in] SendBuf send data
* @param[in] send_buf_len send data length
*
* @return result
* - 0 Success
* - Other Fail
*/
void i2c_send_data_dma(dmac_channel_number_t dma_channel_num, i2c_device_number_t i2c_num, const uint8_t *SendBuf,
size_t send_buf_len);
/**
* @brief I2c receive data
*
* @param[in] i2c_num i2c number
* @param[in] SendBuf send data address
* @param[in] send_buf_len length of send buf
* @param[in] receive_buf receive buf address
* @param[in] receive_buf_len length of receive buf
*
* @return result
* - 0 Success
* - Other Fail
*/
int i2c_recv_data(i2c_device_number_t i2c_num, const uint8_t *SendBuf, size_t send_buf_len, uint8_t *receive_buf,
size_t receive_buf_len);
/**
* @brief I2c receive data by dma
*
* @param[in] dma_send_channel_num send dma channel
* @param[in] dma_receive_channel_num receive dma channel
* @param[in] i2c_num i2c number
* @param[in] SendBuf send data address
* @param[in] send_buf_len length of send buf
* @param[in] receive_buf receive buf address
* @param[in] receive_buf_len length of receive buf
*
* @return result
* - 0 Success
* - Other Fail
*/
void i2c_recv_data_dma(dmac_channel_number_t dma_send_channel_num, dmac_channel_number_t dma_receive_channel_num,
i2c_device_number_t i2c_num, const uint8_t *SendBuf, size_t send_buf_len,
uint8_t *receive_buf, size_t receive_buf_len);
/**
* @brief I2c handle transfer data operations
*
* @param[in] i2c_num i2c number
* @param[in] data i2c data information
* @param[in] cb i2c dma callback
*
*/
void i2c_handle_data_dma(i2c_device_number_t i2c_num, i2c_data_t data, plic_interrupt_t *cb);
#ifdef __cplusplus
}
#endif
#endif /* __HARDWARE_I2C_H__ */

View File

@ -0,0 +1,443 @@
/* Copyright 2018 Canaan Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* @file hardware_rtc.h
* @brief add from Canaan k210 SDK
* https://canaan-creative.com/developer
* @version 1.0
* @author AIIT XUOS Lab
* @date 2021-04-25
*/
#ifndef __HARDWARE_RTC_H__
#define __HARDWARE_RTC_H__
#include <stdint.h>
#include <time.h>
#include "platform.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief RTC timer mode
*
* Timer mode selector
* | Mode | Description |
* |------|------------------------|
* | 0 | Timer pause |
* | 1 | Timer time running |
* | 2 | Timer time setting |
*/
typedef enum _rtc_timer_mode_e
{
/* 0: Timer pause */
RTC_TIMER_PAUSE,
/* 1: Timer time running */
RTC_TIMER_RUNNING,
/* 2: Timer time setting */
RTC_TIMER_SETTING,
/* Max count of this enum*/
RTC_TIMER_MAX
} rtc_timer_mode_t;
/*
* @brief RTC tick interrupt mode
*
* Tick interrupt mode selector
* | Mode | Description |
* |------|------------------------|
* | 0 | Interrupt every second |
* | 1 | Interrupt every minute |
* | 2 | Interrupt every hour |
* | 3 | Interrupt every day |
*/
typedef enum _rtc_tick_interrupt_mode_e
{
/* 0: Interrupt every second */
RTC_INT_SECOND,
/* 1: Interrupt every minute */
RTC_INT_MINUTE,
/* 2: Interrupt every hour */
RTC_INT_HOUR,
/* 3: Interrupt every day */
RTC_INT_DAY,
/* Max count of this enum*/
RTC_INT_MAX
} rtc_tick_interrupt_mode_t;
/**
* @brief RTC mask structure
*
* RTC mask structure for common use
*/
typedef struct _rtc_mask
{
/* Reserved */
uint32_t resv : 1;
/* Second mask */
uint32_t second : 1;
/* Minute mask */
uint32_t minute : 1;
/* Hour mask */
uint32_t hour : 1;
/* Week mask */
uint32_t week : 1;
/* Day mask */
uint32_t day : 1;
/* Month mask */
uint32_t month : 1;
/* Year mask */
uint32_t year : 1;
} __attribute__((packed, aligned(1))) rtc_mask_t;
/**
* @brief RTC register
*
* @note RTC register table
*
* | Offset | Name | Description |
* |-----------|----------------|-------------------------------------|
* | 0x00 | date | Timer date information |
* | 0x04 | time | Timer time information |
* | 0x08 | alarm_date | Alarm date information |
* | 0x0c | alarm_time | Alarm time information |
* | 0x10 | initial_count | Timer counter initial value |
* | 0x14 | current_count | Timer counter current value |
* | 0x18 | interrupt_ctrl | RTC interrupt settings |
* | 0x1c | register_ctrl | RTC register settings |
* | 0x20 | reserved0 | Reserved |
* | 0x24 | reserved1 | Reserved |
* | 0x28 | extended | Timer extended information |
*
*/
/**
* @brief Timer date information
*
* No. 0 Register (0x00)
*/
typedef struct _rtc_date
{
/* Week. Range [0,6]. 0 is Sunday. */
uint32_t week : 3;
/* Reserved */
uint32_t resv0 : 5;
/* Day. Range [1,31] or [1,30] or [1,29] or [1,28] */
uint32_t day : 5;
/* Reserved */
uint32_t resv1 : 3;
/* Month. Range [1,12] */
uint32_t month : 4;
/* Year. Range [0,99] */
uint32_t year : 12;
} __attribute__((packed, aligned(4))) rtc_date_t;
/**
* @brief Timer time information
*
* No. 1 Register (0x04)
*/
typedef struct _rtc_time
{
/* Reserved */
uint32_t resv0 : 10;
/* Second. Range [0,59] */
uint32_t second : 6;
/* Minute. Range [0,59] */
uint32_t minute : 6;
/* Reserved */
uint32_t resv1 : 2;
/* Hour. Range [0,23] */
uint32_t hour : 5;
/* Reserved */
uint32_t resv2 : 3;
} __attribute__((packed, aligned(4))) rtc_time_t;
/**
* @brief Alarm date information
*
* No. 2 Register (0x08)
*/
typedef struct _rtc_alarm_date
{
/* Alarm Week. Range [0,6]. 0 is Sunday. */
uint32_t week : 3;
/* Reserved */
uint32_t resv0 : 5;
/* Alarm Day. Range [1,31] or [1,30] or [1,29] or [1,28] */
uint32_t day : 5;
/* Reserved */
uint32_t resv1 : 3;
/* Alarm Month. Range [1,12] */
uint32_t month : 4;
/* Alarm Year. Range [0,99] */
uint32_t year : 12;
} __attribute__((packed, aligned(4))) rtc_alarm_date_t;
/**
* @brief Alarm time information
*
* No. 3 Register (0x0c)
*/
typedef struct _rtc_alarm_time
{
/* Reserved */
uint32_t resv0 : 10;
/* Alarm Second. Range [0,59] */
uint32_t second : 6;
/* Alarm Minute. Range [0,59] */
uint32_t minute : 6;
/* Reserved */
uint32_t resv1 : 2;
/* Alarm Hour. Range [0,23] */
uint32_t hour : 5;
/* Reserved */
uint32_t resv2 : 3;
} __attribute__((packed, aligned(4))) rtc_alarm_time_t;
/**
* @brief Timer counter initial value
*
* No. 4 Register (0x10)
*/
typedef struct _rtc_initial_count
{
/* RTC counter initial value */
uint32_t count : 32;
} __attribute__((packed, aligned(4))) rtc_initial_count_t;
/**
* @brief Timer counter current value
*
* No. 5 Register (0x14)
*/
typedef struct _rtc_current_count
{
/* RTC counter current value */
uint32_t count : 32;
} __attribute__((packed, aligned(4))) rtc_current_count_t;
/**
* @brief RTC interrupt settings
*
* No. 6 Register (0x18)
*/
typedef struct _rtc_interrupt_ctrl
{
/* Reserved */
uint32_t tick_enable : 1;
/* Alarm interrupt enable */
uint32_t alarm_enable : 1;
/* Tick interrupt enable */
uint32_t tick_int_mode : 2;
/* Reserved */
uint32_t resv : 20;
/* Alarm compare mask for interrupt */
uint32_t alarm_compare_mask : 8;
} __attribute__((packed, aligned(4))) rtc_interrupt_ctrl_t;
/**
* @brief RTC register settings
*
* No. 7 Register (0x1c)
*/
typedef struct _rtc_register_ctrl
{
/* RTC timer read enable */
uint32_t read_enable : 1;
/* RTC timer write enable */
uint32_t write_enable : 1;
/* Reserved */
uint32_t resv0 : 11;
/* RTC timer mask */
uint32_t TimerMask : 8;
/* RTC alarm mask */
uint32_t alarm_mask : 8;
/* RTC counter initial count value mask */
uint32_t initial_count_mask : 1;
/* RTC interrupt register mask */
uint32_t interrupt_register_mask : 1;
/* Reserved */
uint32_t resv1 : 1;
} __attribute__((packed, aligned(4))) rtc_register_ctrl_t;
/**
* @brief Reserved
*
* No. 8 Register (0x20)
*/
typedef struct _rtc_reserved0
{
/* Reserved */
uint32_t resv : 32;
} __attribute__((packed, aligned(4))) rtc_reserved0_t;
/**
* @brief Reserved
*
* No. 9 Register (0x24)
*/
typedef struct _rtc_reserved1
{
/* Reserved */
uint32_t resv : 32;
} __attribute__((packed, aligned(4))) rtc_reserved1_t;
/**
* @brief Timer extended information
*
* No. 10 Register (0x28)
*/
typedef struct _rtc_extended
{
/* Century. Range [0,31] */
uint32_t century : 5;
/* Is leap year. 1 is leap year, 0 is not leap year */
uint32_t leap_year : 1;
/* Reserved */
uint32_t resv : 26;
} __attribute__((packed, aligned(4))) rtc_extended_t;
/**
* @brief Real-time clock struct
*
* A real-time clock (RTC) is a computer clock that keeps track of
* the current time.
*/
typedef struct _rtc
{
/* No. 0 (0x00): Timer date information */
rtc_date_t date;
/* No. 1 (0x04): Timer time information */
rtc_time_t time;
/* No. 2 (0x08): Alarm date information */
rtc_alarm_date_t alarm_date;
/* No. 3 (0x0c): Alarm time information */
rtc_alarm_time_t alarm_time;
/* No. 4 (0x10): Timer counter initial value */
rtc_initial_count_t initial_count;
/* No. 5 (0x14): Timer counter current value */
rtc_current_count_t current_count;
/* No. 6 (0x18): RTC interrupt settings */
rtc_interrupt_ctrl_t interrupt_ctrl;
/* No. 7 (0x1c): RTC register settings */
rtc_register_ctrl_t register_ctrl;
/* No. 8 (0x20): Reserved */
rtc_reserved0_t reserved0;
/* No. 9 (0x24): Reserved */
rtc_reserved1_t reserved1;
/* No. 10 (0x28): Timer extended information */
rtc_extended_t extended;
} __attribute__((packed, aligned(4))) rtc_t;
/**
* @brief Real-time clock object
*/
extern volatile rtc_t *const rtc;
extern volatile uint32_t *const rtc_base;
/**
* @brief Set date time to RTC
*
* @param[in] year The year
* @param[in] month The month
* @param[in] day The day
* @param[in] hour The hour
* @param[in] minute The minute
* @param[in] second The second
*
* @return result
* - 0 Success
* - Other Fail
*/
int rtc_timer_set(int year, int month, int day, int hour, int minute, int second);
/**
* @brief Get date time from RTC
*
* @param year The year
* @param month The month
* @param day The day
* @param hour The hour
* @param minute The minute
* @param second The second
*
* @return result
* - 0 Success
* - Other Fail
*/
int rtc_timer_get(int *year, int *month, int *day, int *hour, int *minute, int *second);
/**
* @brief Initialize RTC
*
* @return Result
* - 0 Success
* - Other Fail
*/
int rtc_init(void);
/**
* @brief Set RTC in protect mode or not
*
* @param enable Enable flag
*
* @return result
* - 0 Success
* - Other Fail
*/
int rtc_protect_set(int enable);
/**
* @brief Set RTC timer mode
*
* @param timer_mode Timer mode
*
*/
void rtc_timer_set_mode(rtc_timer_mode_t timer_mode);
/**
* @brief Set RTC timer clock frequency
*
* @param frequency Frequency
*
* @return result
* - 0 Success
* - Other Fail
*/
int rtc_timer_set_clock_frequency(unsigned int frequency);
/**
* @brief Set RTC timer clock count value
*
* @param count Count
*
* @return result
* - 0 Success
* - Other Fail
*/
int rtc_timer_set_clock_count_value(unsigned int count);
#ifdef __cplusplus
}
#endif
#endif /* _DRIVER_RTC_H */

View File

@ -0,0 +1,494 @@
/* Copyright 2018 Canaan Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* @file hardware_spi.h
* @brief add from Canaan k210 SDK
* https://canaan-creative.com/developer
* @version 1.0
* @author AIIT XUOS Lab
* @date 2021-04-25
*/
#ifndef __HARDWARE_SPI_H__
#define __HARDWARE_SPI_H__
#include <stdint.h>
#include <stddef.h>
#include "dmac.h"
#ifdef __cplusplus
extern "C" {
#endif
/* clang-format off */
typedef struct _spi
{
/* SPI Control Register 0 (0x00)*/
volatile uint32_t ctrlr0;
/* SPI Control Register 1 (0x04)*/
volatile uint32_t ctrlr1;
/* SPI Enable Register (0x08)*/
volatile uint32_t ssienr;
/* SPI Microwire Control Register (0x0c)*/
volatile uint32_t mwcr;
/* SPI Slave Enable Register (0x10)*/
volatile uint32_t ser;
/* SPI Baud Rate Select (0x14)*/
volatile uint32_t baudr;
/* SPI Transmit FIFO Threshold Level (0x18)*/
volatile uint32_t txftlr;
/* SPI Receive FIFO Threshold Level (0x1c)*/
volatile uint32_t rxftlr;
/* SPI Transmit FIFO Level Register (0x20)*/
volatile uint32_t txflr;
/* SPI Receive FIFO Level Register (0x24)*/
volatile uint32_t rxflr;
/* SPI Status Register (0x28)*/
volatile uint32_t sr;
/* SPI Interrupt Mask Register (0x2c)*/
volatile uint32_t imr;
/* SPI Interrupt Status Register (0x30)*/
volatile uint32_t isr;
/* SPI Raw Interrupt Status Register (0x34)*/
volatile uint32_t risr;
/* SPI Transmit FIFO Overflow Interrupt Clear Register (0x38)*/
volatile uint32_t txoicr;
/* SPI Receive FIFO Overflow Interrupt Clear Register (0x3c)*/
volatile uint32_t rxoicr;
/* SPI Receive FIFO Underflow Interrupt Clear Register (0x40)*/
volatile uint32_t rxuicr;
/* SPI Multi-Master Interrupt Clear Register (0x44)*/
volatile uint32_t msticr;
/* SPI Interrupt Clear Register (0x48)*/
volatile uint32_t icr;
/* SPI DMA Control Register (0x4c)*/
volatile uint32_t dmacr;
/* SPI DMA Transmit Data Level (0x50)*/
volatile uint32_t dmatdlr;
/* SPI DMA Receive Data Level (0x54)*/
volatile uint32_t dmardlr;
/* SPI Identification Register (0x58)*/
volatile uint32_t idr;
/* SPI DWC_ssi component version (0x5c)*/
volatile uint32_t ssic_version_id;
/* SPI Data Register 0-36 (0x60 -- 0xec)*/
volatile uint32_t dr[36];
/* SPI RX Sample Delay Register (0xf0)*/
volatile uint32_t rx_sample_delay;
/* SPI SPI Control Register (0xf4)*/
volatile uint32_t spi_ctrlr0;
/* reserved (0xf8)*/
volatile uint32_t resv;
/* SPI XIP Mode bits (0xfc)*/
volatile uint32_t xip_mode_bits;
/* SPI XIP INCR transfer opcode (0x100)*/
volatile uint32_t xip_incr_inst;
/* SPI XIP WRAP transfer opcode (0x104)*/
volatile uint32_t xip_wrap_inst;
/* SPI XIP Control Register (0x108)*/
volatile uint32_t xip_ctrl;
/* SPI XIP Slave Enable Register (0x10c)*/
volatile uint32_t xip_ser;
/* SPI XIP Receive FIFO Overflow Interrupt Clear Register (0x110)*/
volatile uint32_t xrxoicr;
/* SPI XIP time out register for continuous transfers (0x114)*/
volatile uint32_t xip_cnt_time_out;
volatile uint32_t endian;
} __attribute__((packed, aligned(4))) spi_t;
/* clang-format on */
typedef enum _spi_device_num
{
SPI_DEVICE_0,
SPI_DEVICE_1,
SPI_DEVICE_2,
SPI_DEVICE_3,
SPI_DEVICE_MAX,
} spi_device_num_t;
typedef enum _spi_work_mode
{
SPI_WORK_MODE_0,
SPI_WORK_MODE_1,
SPI_WORK_MODE_2,
SPI_WORK_MODE_3,
} spi_work_mode_t;
typedef enum _spi_frame_format
{
SPI_FF_STANDARD,
SPI_FF_DUAL,
SPI_FF_QUAD,
SPI_FF_OCTAL
} spi_frame_format_t;
typedef enum _spi_instruction_address_trans_mode
{
SPI_AITM_STANDARD,
SPI_AITM_ADDR_STANDARD,
SPI_AITM_AS_FRAME_FORMAT
} spi_instruction_address_trans_mode_t;
typedef enum _spi_transfer_mode
{
SPI_TMOD_TRANS_RECV,
SPI_TMOD_TRANS,
SPI_TMOD_RECV,
SPI_TMOD_EEROM
} spi_transfer_mode_t;
typedef enum _spi_transfer_width
{
SPI_TRANS_CHAR = 0x1,
SPI_TRANS_SHORT = 0x2,
SPI_TRANS_INT = 0x4,
} spi_transfer_width_t;
typedef enum _spi_chip_select
{
SPI_CHIP_SELECT_0,
SPI_CHIP_SELECT_1,
SPI_CHIP_SELECT_2,
SPI_CHIP_SELECT_3,
SPI_CHIP_SELECT_MAX,
} spi_chip_select_t;
typedef enum
{
WRITE_CONFIG,
READ_CONFIG,
WRITE_DATA_BYTE,
READ_DATA_BYTE,
WRITE_DATA_BLOCK,
READ_DATA_BLOCK,
} spi_slave_command_e;
typedef struct
{
uint8_t cmd;
uint8_t err;
uint32_t addr;
uint32_t len;
} spi_slave_command_t;
typedef enum
{
IDLE,
COMMAND,
TRANSFER,
} spi_slave_status_e;
typedef int (*spi_slave_receive_callback_t)(void *ctx);
typedef struct _spi_slave_instance
{
uint8_t int_pin;
uint8_t ready_pin;
dmac_channel_number_t dmac_channel;
uint8_t dfs;
uint8_t slv_oe;
uint8_t work_mode;
size_t data_bit_length;
volatile spi_slave_status_e status;
volatile spi_slave_command_t command;
volatile uint8_t *config_ptr;
uint32_t config_len;
spi_slave_receive_callback_t callback;
} spi_slave_instance_t;
typedef struct _spi_data_t
{
dmac_channel_number_t tx_channel;
dmac_channel_number_t rx_channel;
uint32_t *tx_buf;
size_t tx_len;
uint32_t *rx_buf;
size_t rx_len;
spi_transfer_mode_t TransferMode;
bool fill_mode;
} spi_data_t;
extern volatile spi_t *const spi[4];
/**
* @brief Set spi configuration
*
* @param[in] spi_num Spi bus number
* @param[in] mode Spi mode
* @param[in] frame_format Spi frame format
* @param[in] data_bit_length Spi data bit length
* @param[in] endian 0:little-endian 1:big-endian
*
* @return Void
*/
void spi_init(spi_device_num_t spi_num, spi_work_mode_t work_mode, spi_frame_format_t frame_format,
size_t data_bit_length, uint32_t endian);
/**
* @brief Set multiline configuration
*
* @param[in] spi_num Spi bus number
* @param[in] instruction_length Instruction length
* @param[in] address_length Address length
* @param[in] wait_cycles Wait cycles
* @param[in] instruction_address_trans_mode Spi transfer mode
*
*/
void spi_init_non_standard(spi_device_num_t spi_num, uint32_t instruction_length, uint32_t address_length,
uint32_t wait_cycles, spi_instruction_address_trans_mode_t instruction_address_trans_mode);
/**
* @brief Spi send data
*
* @param[in] spi_num Spi bus number
* @param[in] chip_select Spi chip select
* @param[in] CmdBuff Spi command buffer point
* @param[in] CmdLen Spi command length
* @param[in] tx_buff Spi transmit buffer point
* @param[in] tx_len Spi transmit buffer length
*
* @return Result
* - 0 Success
* - Other Fail
*/
void spi_send_data_standard(spi_device_num_t spi_num, spi_chip_select_t chip_select, const uint8_t *CmdBuff,
size_t CmdLen, const uint8_t *tx_buff, size_t tx_len);
/**
* @brief Spi receive data
*
* @param[in] spi_num Spi bus number
* @param[in] chip_select Spi chip select
* @param[in] CmdBuff Spi command buffer point
* @param[in] CmdLen Spi command length
* @param[in] rx_buff Spi receive buffer point
* @param[in] rx_len Spi receive buffer length
*
* @return Result
* - 0 Success
* - Other Fail
*/
void spi_receive_data_standard(spi_device_num_t spi_num, spi_chip_select_t chip_select, const uint8_t *CmdBuff,
size_t CmdLen, uint8_t *rx_buff, size_t rx_len);
/**
* @brief Spi special receive data
*
* @param[in] spi_num Spi bus number
* @param[in] chip_select Spi chip select
* @param[in] CmdBuff Spi command buffer point
* @param[in] CmdLen Spi command length
* @param[in] rx_buff Spi receive buffer point
* @param[in] rx_len Spi receive buffer length
*
* @return Result
* - 0 Success
* - Other Fail
*/
void spi_receive_data_multiple(spi_device_num_t spi_num, spi_chip_select_t chip_select, const uint32_t *CmdBuff,
size_t CmdLen, uint8_t *rx_buff, size_t rx_len);
/**
* @brief Spi special send data
*
* @param[in] spi_num Spi bus number
* @param[in] chip_select Spi chip select
* @param[in] CmdBuff Spi command buffer point
* @param[in] CmdLen Spi command length
* @param[in] tx_buff Spi transmit buffer point
* @param[in] tx_len Spi transmit buffer length
*
* @return Result
* - 0 Success
* - Other Fail
*/
void spi_send_data_multiple(spi_device_num_t spi_num, spi_chip_select_t chip_select, const uint32_t *CmdBuff,
size_t CmdLen, const uint8_t *tx_buff, size_t tx_len);
/**
* @brief Spi send data by dma
*
* @param[in] channel_num Dmac channel number
* @param[in] spi_num Spi bus number
* @param[in] chip_select Spi chip select
* @param[in] CmdBuff Spi command buffer point
* @param[in] CmdLen Spi command length
* @param[in] tx_buff Spi transmit buffer point
* @param[in] tx_len Spi transmit buffer length
*
* @return Result
* - 0 Success
* - Other Fail
*/
void spi_send_data_standard_dma(dmac_channel_number_t channel_num, spi_device_num_t spi_num,
spi_chip_select_t chip_select,
const uint8_t *CmdBuff, size_t CmdLen, const uint8_t *tx_buff, size_t tx_len);
/**
* @brief Spi receive data by dma
*
* @param[in] w_channel_num Dmac write channel number
* @param[in] r_channel_num Dmac read channel number
* @param[in] spi_num Spi bus number
* @param[in] chip_select Spi chip select
* @param[in] CmdBuff Spi command buffer point
* @param[in] CmdLen Spi command length
* @param[in] rx_buff Spi receive buffer point
* @param[in] rx_len Spi receive buffer length
*
* @return Result
* - 0 Success
* - Other Fail
*/
void spi_receive_data_standard_dma(dmac_channel_number_t dma_send_channel_num,
dmac_channel_number_t dma_receive_channel_num,
spi_device_num_t spi_num, spi_chip_select_t chip_select, const uint8_t *CmdBuff,
size_t CmdLen, uint8_t *rx_buff, size_t rx_len);
/**
* @brief Spi special send data by dma
*
* @param[in] channel_num Dmac channel number
* @param[in] spi_num Spi bus number
* @param[in] chip_select Spi chip select
* @param[in] CmdBuff Spi command buffer point
* @param[in] CmdLen Spi command length
* @param[in] tx_buff Spi transmit buffer point
* @param[in] tx_len Spi transmit buffer length
*
* @return Result
* - 0 Success
* - Other Fail
*/
void spi_send_data_multiple_dma(dmac_channel_number_t channel_num, spi_device_num_t spi_num,
spi_chip_select_t chip_select,
const uint32_t *CmdBuff, size_t CmdLen, const uint8_t *tx_buff, size_t tx_len);
/**
* @brief Spi special receive data by dma
*
* @param[in] dma_send_channel_num Dmac write channel number
* @param[in] dma_receive_channel_num Dmac read channel number
* @param[in] spi_num Spi bus number
* @param[in] chip_select Spi chip select
* @param[in] CmdBuff Spi command buffer point
* @param[in] CmdLen Spi command length
* @param[in] rx_buff Spi receive buffer point
* @param[in] rx_len Spi receive buffer length
*
* @return Result
* - 0 Success
* - Other Fail
*/
void spi_receive_data_multiple_dma(dmac_channel_number_t dma_send_channel_num,
dmac_channel_number_t dma_receive_channel_num,
spi_device_num_t spi_num, spi_chip_select_t chip_select, const uint32_t *CmdBuff,
size_t CmdLen, uint8_t *rx_buff, size_t rx_len);
/**
* @brief Spi fill dma
*
* @param[in] channel_num Dmac channel number
* @param[in] spi_num Spi bus number
* @param[in] chip_select Spi chip select
* @param[in] tx_buff Spi command buffer point
* @param[in] tx_len Spi command length
*
* @return Result
* - 0 Success
* - Other Fail
*/
void spi_fill_data_dma(dmac_channel_number_t channel_num, spi_device_num_t spi_num, spi_chip_select_t chip_select,
const uint32_t *tx_buff, size_t tx_len);
/**
* @brief Spi normal send by dma
*
* @param[in] channel_num Dmac channel number
* @param[in] spi_num Spi bus number
* @param[in] chip_select Spi chip select
* @param[in] tx_buff Spi transmit buffer point
* @param[in] tx_len Spi transmit buffer length
* @param[in] stw Spi transfer width
*
* @return Result
* - 0 Success
* - Other Fail
*/
void spi_send_data_normal_dma(dmac_channel_number_t channel_num, spi_device_num_t spi_num,
spi_chip_select_t chip_select,
const void *tx_buff, size_t tx_len, spi_transfer_width_t spi_transfer_width);
/**
* @brief Spi normal send by dma
*
* @param[in] spi_num Spi bus number
* @param[in] spi_clk Spi clock rate
*
* @return The real spi clock rate
*/
uint32_t spi_set_clk_rate(spi_device_num_t spi_num, uint32_t spi_clk);
/**
* @brief Spi full duplex send receive data by dma
*
* @param[in] dma_send_channel_num Dmac write channel number
* @param[in] dma_receive_channel_num Dmac read channel number
* @param[in] spi_num Spi bus number
* @param[in] chip_select Spi chip select
* @param[in] tx_buf Spi send buffer
* @param[in] tx_len Spi send buffer length
* @param[in] rx_buf Spi receive buffer
* @param[in] rx_len Spi receive buffer length
*
*/
void spi_dup_send_receive_data_dma(dmac_channel_number_t dma_send_channel_num,
dmac_channel_number_t dma_receive_channel_num,
spi_device_num_t spi_num, spi_chip_select_t chip_select,
const uint8_t *tx_buf, size_t tx_len, uint8_t *rx_buf, size_t rx_len);
/**
* @brief Set spi slave configuration
*
* @param[in] int_pin SPI master starts sending data interrupt.
* @param[in] ready_pin SPI slave ready.
* @param[in] dmac_channel Dmac channel number for block.
* @param[in] data_bit_length Spi data bit length
* @param[in] data SPI slave device data buffer.
* @param[in] len The length of SPI slave device data buffer.
* @param[in] callback Callback of spi slave.
*
* @return Void
*/
void spi_slave_config(uint8_t int_pin, uint8_t ready_pin, dmac_channel_number_t dmac_channel, size_t data_bit_length, uint8_t *data, uint32_t len, spi_slave_receive_callback_t callback);
/**
* @brief Spi handle transfer data operations
*
* @param[in] spi_num Spi bus number
* @param[in] chip_select Spi chip select
* @param[in] data Spi transfer data information
* @param[in] cb Spi DMA callback
*
*/
void spi_handle_data_dma(spi_device_num_t spi_num, spi_chip_select_t chip_select, spi_data_t data, plic_interrupt_t *cb);
#ifdef __cplusplus
}
#endif
#endif /* __HARDWARE_SPI_H__ */

View File

@ -0,0 +1,364 @@
/* Copyright 2018 Canaan Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* @file
* @brief Universal Asynchronous Receiver/Transmitter (UART)
*
* The UART peripheral supports the following features:
*
* - 8-N-1 and 8-N-2 formats: 8 data bits, no parity bit, 1 start
* bit, 1 or 2 stop bits
*
* - 8-entry transmit and receive FIFO buffers with programmable
* watermark interrupts
*
* - 16× Rx oversampling with 2/3 majority voting per bit
*
* The UART peripheral does not support hardware flow control or
* other modem control signals, or synchronous serial data
* tranfesrs.
*
*
*/
/**
* @file hardware_uart.h
* @brief add from Canaan k210 SDK
* https://canaan-creative.com/developer
* @version 1.0
* @author AIIT XUOS Lab
* @date 2021-04-25
*/
#ifndef __HARDWARE_UART_H__
#define __HARDWARE_UART_H__
#include <stdint.h>
#include "platform.h"
#include "plic.h"
#include "dmac.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef enum _uart_dev
{
UART_DEV1 = 0,
UART_DEV2,
UART_DEV3,
} uart_dev_t;
typedef struct _uart
{
union
{
volatile uint32_t RBR;
volatile uint32_t DLL;
volatile uint32_t THR;
};
union
{
volatile uint32_t DLH;
volatile uint32_t IER;
};
union
{
volatile uint32_t FCR;
volatile uint32_t IIR;
};
volatile uint32_t LCR;
volatile uint32_t MCR;
volatile uint32_t LSR;
volatile uint32_t MSR;
volatile uint32_t SCR;
volatile uint32_t LPDLL;
volatile uint32_t LPDLH;
volatile uint32_t reserved1[2];
union
{
volatile uint32_t SRBR[16];
volatile uint32_t STHR[16];
};
volatile uint32_t FAR;
volatile uint32_t TFR;
volatile uint32_t RFW;
volatile uint32_t USR;
volatile uint32_t TFL;
volatile uint32_t RFL;
volatile uint32_t SRR;
volatile uint32_t SRTS;
volatile uint32_t SBCR;
volatile uint32_t SDMAM;
volatile uint32_t SFE;
volatile uint32_t SRT;
volatile uint32_t STET;
volatile uint32_t HTX;
volatile uint32_t DMASA;
volatile uint32_t TCR;
volatile uint32_t DE_EN;
volatile uint32_t RE_EN;
volatile uint32_t DET;
volatile uint32_t TAT;
volatile uint32_t DLF;
volatile uint32_t RAR;
volatile uint32_t TAR;
volatile uint32_t LCR_EXT;
volatile uint32_t reserved2[9];
volatile uint32_t CPR;
volatile uint32_t UCV;
volatile uint32_t CTR;
} UartT;
typedef enum _uart_device_number
{
UART_DEVICE_1,
UART_DEVICE_2,
UART_DEVICE_3,
UART_DEVICE_MAX,
} UartDeviceNumberT;
typedef enum _uart_bitwidth
{
UART_BITWIDTH_5BIT = 5,
UART_BITWIDTH_6BIT,
UART_BITWIDTH_7BIT,
UART_BITWIDTH_8BIT,
} UartBitwidthPointer;
typedef enum _uart_stopbit
{
UART_STOP_1,
UART_STOP_1_5,
UART_STOP_2
} UartStopbitT;
typedef enum _uart_rede_sel
{
DISABLE = 0,
ENABLE,
} uart_rede_sel_t;
typedef enum _uart_parity
{
UART_PARITY_NONE,
UART_PARITY_ODD,
UART_PARITY_EVEN
} UartParityT;
typedef enum _uart_interrupt_mode
{
UART_SEND = 1,
UART_RECEIVE = 2,
} UartInterruptModeT;
typedef enum _uart_send_trigger
{
UART_SEND_FIFO_0,
UART_SEND_FIFO_2,
UART_SEND_FIFO_4,
UART_SEND_FIFO_8,
} uart_send_trigger_t;
typedef enum _uart_receive_trigger
{
UART_RECEIVE_FIFO_1,
UART_RECEIVE_FIFO_4,
UART_RECEIVE_FIFO_8,
UART_RECEIVE_FIFO_14,
} uart_receive_trigger_t;
typedef struct _uart_data_t
{
dmac_channel_number_t tx_channel;
dmac_channel_number_t rx_channel;
uint32_t *tx_buf;
size_t tx_len;
uint32_t *rx_buf;
size_t rx_len;
UartInterruptModeT TransferMode;
} uart_data_t;
/**
* @brief Send data from uart
*
* @param[in] channel Uart index
* @param[in] buffer The data be transfer
* @param[in] len The data length
*
* @return Transfer length
*/
int UartSendData(UartDeviceNumberT channel, const char *buffer, size_t BufLen);
/**
* @brief Read data from uart
*
* @param[in] channel Uart index
* @param[in] buffer The Data received
* @param[in] len Receive length
*
* @return Receive length
*/
int UartReceiveData(UartDeviceNumberT channel, char *buffer, size_t BufLen);
/**
* @brief Init uart
*
* @param[in] channel Uart index
*
*/
void UartInit(UartDeviceNumberT channel);
/**
* @brief Set uart param
*
* @param[in] channel Uart index
* @param[in] BaudRate Baudrate
* @param[in] DataWidth Data width
* @param[in] stopbit Stop bit
* @param[in] parity Odd Even parity
*
*/
void uart_config(UartDeviceNumberT channel, uint32_t BaudRate, UartBitwidthPointer DataWidth, UartStopbitT stopbit, UartParityT parity);
/**
* @brief Set uart param
*
* @param[in] channel Uart index
* @param[in] BaudRate Baudrate
* @param[in] DataWidth Data width
* @param[in] stopbit Stop bit
* @param[in] parity Odd Even parity
*
*/
void uart_configure(UartDeviceNumberT channel, uint32_t BaudRate, UartBitwidthPointer DataWidth, UartStopbitT stopbit, UartParityT parity);
/**
* @brief Register uart interrupt
*
* @param[in] channel Uart index
* @param[in] interrupt_mode Interrupt Mode receive or send
* @param[in] uart_callback Call back
* @param[in] ctx Param of call back
* @param[in] priority Interrupt priority
*
*/
void uart_irq_register(UartDeviceNumberT channel, UartInterruptModeT interrupt_mode, plic_irq_callback_t uart_callback, void *ctx, uint32_t priority);
/**
* @brief Deregister uart interrupt
*
* @param[in] channel Uart index
* @param[in] interrupt_mode Interrupt Mode receive or send
*
*/
void uart_irq_unregister(UartDeviceNumberT channel, UartInterruptModeT interrupt_mode);
/**
* @brief Set send interrupt threshold
*
* @param[in] channel Uart index
* @param[in] trigger Threshold of send interrupt
*
*/
void UartSetSendTrigger(UartDeviceNumberT channel, uart_send_trigger_t trigger);
/**
* @brief Set receive interrupt threshold
*
* @param[in] channel Uart index
* @param[in] trigger Threshold of receive interrupt
*
*/
void uart_set_receive_trigger(UartDeviceNumberT channel, uart_receive_trigger_t trigger);
/**
* @brief Send data by dma
*
* @param[in] channel Uart index
* @param[in] dmac_channel Dmac channel
* @param[in] buffer Send data
* @param[in] BufLen Data length
*
*/
void UartSendDataDma(UartDeviceNumberT uart_channel, dmac_channel_number_t dmac_channel, const uint8_t *buffer, size_t BufLen);
/**
* @brief Receive data by dma
*
* @param[in] channel Uart index
* @param[in] dmac_channel Dmac channel
* @param[in] buffer Receive data
* @param[in] BufLen Data length
*
*/
void UartReceiveDataDma(UartDeviceNumberT uart_channel, dmac_channel_number_t dmac_channel, uint8_t *buffer, size_t BufLen);
/**
* @brief Send data by dma
*
* @param[in] uart_channel Uart index
* @param[in] dmac_channel Dmac channel
* @param[in] buffer Send data
* @param[in] BufLen Data length
* @param[in] uart_callback Call back
* @param[in] ctx Param of call back
* @param[in] priority Interrupt priority
*
*/
void UartSendDataDmaIrq(UartDeviceNumberT uart_channel, dmac_channel_number_t dmac_channel,
const uint8_t *buffer, size_t BufLen, plic_irq_callback_t uart_callback,
void *ctx, uint32_t priority);
/**
* @brief Receive data by dma
*
* @param[in] uart_channel Uart index
* @param[in] dmac_channel Dmac channel
* @param[in] buffer Receive data
* @param[in] BufLen Data length
* @param[in] uart_callback Call back
* @param[in] ctx Param of call back
* @param[in] priority Interrupt priority
*
*/
void UartReceiveDataDmaIrq(UartDeviceNumberT uart_channel, dmac_channel_number_t dmac_channel,
uint8_t *buffer, size_t BufLen, plic_irq_callback_t uart_callback,
void *ctx, uint32_t priority);
/**
* @brief Uart handle transfer data operations
*
* @param[in] uart_channel Uart index
* @param[in] data Uart data information
* @param[in] buffer Uart DMA callback
*
*/
void uart_handle_data_dma(UartDeviceNumberT uart_channel ,uart_data_t data, plic_interrupt_t *cb);
#ifdef __cplusplus
}
#endif
#endif /* __UART_H__ */

View File

@ -0,0 +1,302 @@
/* Copyright 2018 Canaan Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* @file
* @brief Universal Asynchronous Receiver/Transmitter (UART)
*
* The UART peripheral supports the following features:
*
* - 8-N-1 and 8-N-2 formats: 8 data bits, no parity bit, 1 start
* bit, 1 or 2 stop bits
*
* - 8-entry transmit and receive FIFO buffers with programmable
* watermark interrupts
*
* - 16× Rx oversampling with 2/3 majority voting per bit
*
* The UART peripheral does not support hardware flow control or
* other modem control signals, or synchronous serial data
* tranfesrs.
*
* @note UART RAM Layout
*
* | Address | Name | Description |
* |-----------|----------|---------------------------------|
* | 0x000 | txdata | Transmit data register |
* | 0x004 | rxdata | Receive data register |
* | 0x008 | txctrl | Transmit control register |
* | 0x00C | rxctrl | Receive control register |
* | 0x010 | ie | UART interrupt enable |
* | 0x014 | ip | UART Interrupt pending |
* | 0x018 | div | Baud rate divisor |
*
*/
/**
* @file hardware_uarths.h
* @brief add from Canaan k210 SDK
* https://canaan-creative.com/developer
* @version 1.0
* @author AIIT XUOS Lab
* @date 2021-04-25
*/
#ifndef __HARDWARE_UARTHS_H__
#define __HARDWARE_UARTHS_H__
#include <stddef.h>
#include <stdint.h>
#include "platform.h"
#include "plic.h"
#ifdef __cplusplus
extern "C" {
#endif
/* clang-format off */
/* Register address offsets */
#define UARTHS_REG_TXFIFO (0x00)
#define UARTHS_REG_RXFIFO (0x04)
#define UARTHS_REG_TXCTRL (0x08)
#define UARTHS_REG_RXCTRL (0x0c)
#define UARTHS_REG_IE (0x10)
#define UARTHS_REG_IP (0x14)
#define UARTHS_REG_DIV (0x18)
/* TXCTRL register */
#define UARTHS_TXEN (0x01)
#define UARTHS_TXWM(x) (((x) & 0xffff) << 16)
/* RXCTRL register */
#define UARTHS_RXEN (0x01)
#define UARTHS_RXWM(x) (((x) & 0xffff) << 16)
/* IP register */
#define UARTHS_IP_TXWM (0x01)
#define UARTHS_IP_RXWM (0x02)
/* clang-format on */
typedef struct _uarths_txdata
{
/* Bits [7:0] is data */
uint32_t data : 8;
/* Bits [30:8] is 0 */
uint32_t zero : 23;
/* Bit 31 is full status */
uint32_t full : 1;
} __attribute__((packed, aligned(4))) uarths_txdata_t;
typedef struct _uarths_rxdata
{
/* Bits [7:0] is data */
uint32_t data : 8;
/* Bits [30:8] is 0 */
uint32_t zero : 23;
/* Bit 31 is empty status */
uint32_t empty : 1;
} __attribute__((packed, aligned(4))) uarths_rxdata_t;
typedef struct _uarths_txctrl
{
/* Bit 0 is txen, controls whether the Tx channel is active. */
uint32_t txen : 1;
/* Bit 1 is nstop, 0 for one stop bit and 1 for two stop bits */
uint32_t nstop : 1;
/* Bits [15:2] is reserved */
uint32_t resv0 : 14;
/* Bits [18:16] is threshold of interrupt triggers */
uint32_t txcnt : 3;
/* Bits [31:19] is reserved */
uint32_t resv1 : 13;
} __attribute__((packed, aligned(4))) uarths_txctrl_t;
typedef struct _uarths_rxctrl
{
/* Bit 0 is txen, controls whether the Tx channel is active. */
uint32_t rxen : 1;
/* Bits [15:1] is reserved */
uint32_t resv0 : 15;
/* Bits [18:16] is threshold of interrupt triggers */
uint32_t rxcnt : 3;
/* Bits [31:19] is reserved */
uint32_t resv1 : 13;
} __attribute__((packed, aligned(4))) uarths_rxctrl_t;
typedef struct _uarths_ip
{
/* Bit 0 is txwm, raised less than txcnt */
uint32_t txwm : 1;
/* Bit 1 is txwm, raised greater than rxcnt */
uint32_t rxwm : 1;
/* Bits [31:2] is 0 */
uint32_t zero : 30;
} __attribute__((packed, aligned(4))) uarths_ip_t;
typedef struct _uarths_ie
{
/* Bit 0 is txwm, raised less than txcnt */
uint32_t txwm : 1;
/* Bit 1 is txwm, raised greater than rxcnt */
uint32_t rxwm : 1;
/* Bits [31:2] is 0 */
uint32_t zero : 30;
} __attribute__((packed, aligned(4))) uarths_ie_t;
typedef struct _uarths_div
{
/* Bits [31:2] is baud rate divisor register */
uint32_t div : 16;
/* Bits [31:16] is 0 */
uint32_t zero : 16;
} __attribute__((packed, aligned(4))) uarths_div_t;
typedef struct _uarths
{
/* Address offset 0x00 */
uarths_txdata_t txdata;
/* Address offset 0x04 */
uarths_rxdata_t rxdata;
/* Address offset 0x08 */
uarths_txctrl_t txctrl;
/* Address offset 0x0c */
uarths_rxctrl_t rxctrl;
/* Address offset 0x10 */
uarths_ie_t ie;
/* Address offset 0x14 */
uarths_ip_t ip;
/* Address offset 0x18 */
uarths_div_t div;
} __attribute__((packed, aligned(4))) UarthsT;
typedef enum _uarths_interrupt_mode
{
UARTHS_SEND = 1,
UARTHS_RECEIVE = 2,
UARTHS_SEND_RECEIVE = 3,
} uarths_interrupt_mode_t;
typedef enum _uarths_stopbit
{
UARTHS_STOP_1,
UARTHS_STOP_2
} uarths_stopbit_t;
extern volatile UarthsT *const uarths;
/**
* @brief Initialization Core UART
*
* @return result
* - 0 Success
* - Other Fail
*/
void uarths_init(void);
/**
* @brief Put a char to UART
*
* @param[in] c The char to put
*
* @note If c is '\n', a '\r' will be appended automatically
*
* @return result
* - 0 Success
* - Other Fail
*/
int uarths_putchar(char c);
/**
* @brief Send a string to UART
*
* @param[in] s The string to send
*
* @note The string must ending with '\0'
*
* @return result
* - 0 Success
* - Other Fail
*/
int uarths_puts(const char *s);
/**
* @brief Get a byte from UART
*
* @return byte as int type from UART
*/
int uarths_getc(void);
/**
* @brief Set uarths interrupt callback
*
* @param[in] interrupt_mode Interrupt mode recevice or send
* @param[in] uarths_callback Interrupt callback
* @param[in] ctx Param of callback
* @param[in] priority Interrupt priority
*
*/
void uarths_set_irq(uarths_interrupt_mode_t interrupt_mode, plic_irq_callback_t uarths_callback, void *ctx, uint32_t priority);
/**
* @brief Uarths receive data
*
* @param[in] buf The data received
* @param[in] BufLen The length of data
*
* @return Number of received data
*/
size_t uarths_receive_data(uint8_t *buf, size_t BufLen);
/**
* @brief Uarths receive data
*
* @param[in] buf The data sended
* @param[in] BufLen The length of data
*
* @return Number of sended data
*/
size_t uarths_send_data(const uint8_t *buf, size_t BufLen);
/**
* @brief Get interrupt mode
*
* @return Mode of interrupt
*/
uarths_interrupt_mode_t uarths_get_interrupt_mode(void);
/**
* @brief Set uarths baud rate and stopbit
*
* @param[in] BaudRate The baud rate
* @param[in] stopbit The stopbit of data
*
*/
void uarths_config(uint32_t BaudRate, uarths_stopbit_t stopbit);
/**
* @brief Set uart interrupt condition
*
* @param[in] interrupt_mode The interrupt mode
* @param[in] cnt The count of tigger
*
*/
void uarths_set_interrupt_cnt(uarths_interrupt_mode_t interrupt_mode, uint8_t cnt);
#ifdef __cplusplus
}
#endif
#endif /* __UARTHS_H__ */

View File

@ -0,0 +1,60 @@
/* Copyright 2018 Canaan Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* @file io.h
* @brief add from Canaan k210 SDK
* https://canaan-creative.com/developer
* @version 1.0
* @author AIIT XUOS Lab
* @date 2021-04-25
*/
#ifndef __IO_H__
#define __IO_H__
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
#define readb(addr) (*(volatile uint8_t *)(addr))
#define readw(addr) (*(volatile uint16_t *)(addr))
#define readl(addr) (*(volatile uint32_t *)(addr))
#define readq(addr) (*(volatile uint64_t *)(addr))
#define writeb(v, addr) \
{ \
(*(volatile uint8_t *)(addr)) = (v); \
}
#define writew(v, addr) \
{ \
(*(volatile uint16_t *)(addr)) = (v); \
}
#define writel(v, addr) \
{ \
(*(volatile uint32_t *)(addr)) = (v); \
}
#define writeq(v, addr) \
{ \
(*(volatile uint64_t *)(addr)) = (v); \
}
#ifdef __cplusplus
}
#endif
#endif /* __IO_H__ */

View File

@ -0,0 +1,467 @@
/* Copyright 2018 Canaan Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* @file plic.h
* @brief add from Canaan k210 SDK
* https://canaan-creative.com/developer
* @version 1.0
* @author AIIT XUOS Lab
* @date 2021-04-25
*/
#ifndef __PLIC_H__
#define __PLIC_H__
#include <stdint.h>
#include "encoding.h"
#include "platform.h"
/* For c++ compatibility */
#ifdef __cplusplus
extern "C" {
#endif
/* clang-format off */
/* IRQ number settings */
#define PLIC_NUM_SOURCES (IRQN_MAX - 1)
#define PLIC_NUM_PRIORITIES (7)
/* Real number of cores */
#define PLIC_NUM_CORES (2)
/* clang-format on */
/**
* @brief PLIC External Interrupt Numbers
*
* @note PLIC interrupt sources
*
* | Source | Name | Description |
* |--------|--------------------------|------------------------------------|
* | 0 | IRQN_NO_INTERRUPT | The non-existent interrupt |
* | 1 | IRQN_SPI0_INTERRUPT | SPI0 interrupt |
* | 2 | IRQN_SPI1_INTERRUPT | SPI1 interrupt |
* | 3 | IRQN_SPI_SLAVE_INTERRUPT | SPI_SLAVE interrupt |
* | 4 | IRQN_SPI3_INTERRUPT | SPI3 interrupt |
* | 5 | IRQN_I2S0_INTERRUPT | I2S0 interrupt |
* | 6 | IRQN_I2S1_INTERRUPT | I2S1 interrupt |
* | 7 | IRQN_I2S2_INTERRUPT | I2S2 interrupt |
* | 8 | IRQN_I2C0_INTERRUPT | I2C0 interrupt |
* | 9 | IRQN_I2C1_INTERRUPT | I2C1 interrupt |
* | 10 | IRQN_I2C2_INTERRUPT | I2C2 interrupt |
* | 11 | IRQN_UART1_INTERRUPT | UART1 interrupt |
* | 12 | IRQN_UART2_INTERRUPT | UART2 interrupt |
* | 13 | IRQN_UART3_INTERRUPT | UART3 interrupt |
* | 14 | IRQN_TIMER0A_INTERRUPT | TIMER0 channel 0 or 1 interrupt |
* | 15 | IRQN_TIMER0B_INTERRUPT | TIMER0 channel 2 or 3 interrupt |
* | 16 | IRQN_TIMER1A_INTERRUPT | TIMER1 channel 0 or 1 interrupt |
* | 17 | IRQN_TIMER1B_INTERRUPT | TIMER1 channel 2 or 3 interrupt |
* | 18 | IRQN_TIMER2A_INTERRUPT | TIMER2 channel 0 or 1 interrupt |
* | 19 | IRQN_TIMER2B_INTERRUPT | TIMER2 channel 2 or 3 interrupt |
* | 20 | IRQN_RTC_INTERRUPT | RTC tick and alarm interrupt |
* | 21 | IRQN_WDT0_INTERRUPT | Watching dog timer0 interrupt |
* | 22 | IRQN_WDT1_INTERRUPT | Watching dog timer1 interrupt |
* | 23 | IRQN_APB_GPIO_INTERRUPT | APB GPIO interrupt |
* | 24 | IRQN_DVP_INTERRUPT | Digital video port interrupt |
* | 25 | IRQN_AI_INTERRUPT | AI accelerator interrupt |
* | 26 | IRQN_FFT_INTERRUPT | FFT accelerator interrupt |
* | 27 | IRQN_DMA0_INTERRUPT | DMA channel0 interrupt |
* | 28 | IRQN_DMA1_INTERRUPT | DMA channel1 interrupt |
* | 29 | IRQN_DMA2_INTERRUPT | DMA channel2 interrupt |
* | 30 | IRQN_DMA3_INTERRUPT | DMA channel3 interrupt |
* | 31 | IRQN_DMA4_INTERRUPT | DMA channel4 interrupt |
* | 32 | IRQN_DMA5_INTERRUPT | DMA channel5 interrupt |
* | 33 | IRQN_UARTHS_INTERRUPT | Hi-speed UART0 interrupt |
* | 34 | IRQN_GPIOHS0_INTERRUPT | Hi-speed GPIO0 interrupt |
* | 35 | IRQN_GPIOHS1_INTERRUPT | Hi-speed GPIO1 interrupt |
* | 36 | IRQN_GPIOHS2_INTERRUPT | Hi-speed GPIO2 interrupt |
* | 37 | IRQN_GPIOHS3_INTERRUPT | Hi-speed GPIO3 interrupt |
* | 38 | IRQN_GPIOHS4_INTERRUPT | Hi-speed GPIO4 interrupt |
* | 39 | IRQN_GPIOHS5_INTERRUPT | Hi-speed GPIO5 interrupt |
* | 40 | IRQN_GPIOHS6_INTERRUPT | Hi-speed GPIO6 interrupt |
* | 41 | IRQN_GPIOHS7_INTERRUPT | Hi-speed GPIO7 interrupt |
* | 42 | IRQN_GPIOHS8_INTERRUPT | Hi-speed GPIO8 interrupt |
* | 43 | IRQN_GPIOHS9_INTERRUPT | Hi-speed GPIO9 interrupt |
* | 44 | IRQN_GPIOHS10_INTERRUPT | Hi-speed GPIO10 interrupt |
* | 45 | IRQN_GPIOHS11_INTERRUPT | Hi-speed GPIO11 interrupt |
* | 46 | IRQN_GPIOHS12_INTERRUPT | Hi-speed GPIO12 interrupt |
* | 47 | IRQN_GPIOHS13_INTERRUPT | Hi-speed GPIO13 interrupt |
* | 48 | IRQN_GPIOHS14_INTERRUPT | Hi-speed GPIO14 interrupt |
* | 49 | IRQN_GPIOHS15_INTERRUPT | Hi-speed GPIO15 interrupt |
* | 50 | IRQN_GPIOHS16_INTERRUPT | Hi-speed GPIO16 interrupt |
* | 51 | IRQN_GPIOHS17_INTERRUPT | Hi-speed GPIO17 interrupt |
* | 52 | IRQN_GPIOHS18_INTERRUPT | Hi-speed GPIO18 interrupt |
* | 53 | IRQN_GPIOHS19_INTERRUPT | Hi-speed GPIO19 interrupt |
* | 54 | IRQN_GPIOHS20_INTERRUPT | Hi-speed GPIO20 interrupt |
* | 55 | IRQN_GPIOHS21_INTERRUPT | Hi-speed GPIO21 interrupt |
* | 56 | IRQN_GPIOHS22_INTERRUPT | Hi-speed GPIO22 interrupt |
* | 57 | IRQN_GPIOHS23_INTERRUPT | Hi-speed GPIO23 interrupt |
* | 58 | IRQN_GPIOHS24_INTERRUPT | Hi-speed GPIO24 interrupt |
* | 59 | IRQN_GPIOHS25_INTERRUPT | Hi-speed GPIO25 interrupt |
* | 60 | IRQN_GPIOHS26_INTERRUPT | Hi-speed GPIO26 interrupt |
* | 61 | IRQN_GPIOHS27_INTERRUPT | Hi-speed GPIO27 interrupt |
* | 62 | IRQN_GPIOHS28_INTERRUPT | Hi-speed GPIO28 interrupt |
* | 63 | IRQN_GPIOHS29_INTERRUPT | Hi-speed GPIO29 interrupt |
* | 64 | IRQN_GPIOHS30_INTERRUPT | Hi-speed GPIO30 interrupt |
* | 65 | IRQN_GPIOHS31_INTERRUPT | Hi-speed GPIO31 interrupt |
*
*/
/* clang-format off */
typedef enum _plic_irq
{
IRQN_NO_INTERRUPT = 0, /*!< The non-existent interrupt */
IRQN_SPI0_INTERRUPT = 1, /*!< SPI0 interrupt */
IRQN_SPI1_INTERRUPT = 2, /*!< SPI1 interrupt */
IRQN_SPI_SLAVE_INTERRUPT = 3, /*!< SPI_SLAVE interrupt */
//IRQN_SPI3_INTERRUPT = 4, /*!< SPI3 interrupt */
IRQN_I2S0_INTERRUPT = 5, /*!< I2S0 interrupt */
IRQN_I2S1_INTERRUPT = 6, /*!< I2S1 interrupt */
IRQN_I2S2_INTERRUPT = 7, /*!< I2S2 interrupt */
IRQN_I2C0_INTERRUPT = 8, /*!< I2C0 interrupt */
IRQN_I2C1_INTERRUPT = 9, /*!< I2C1 interrupt */
IRQN_I2C2_INTERRUPT = 10, /*!< I2C2 interrupt */
IRQN_UART1_INTERRUPT = 11, /*!< UART1 interrupt */
IRQN_UART2_INTERRUPT = 12, /*!< UART2 interrupt */
IRQN_UART3_INTERRUPT = 13, /*!< UART3 interrupt */
IRQN_TIMER0A_INTERRUPT = 14, /*!< TIMER0 channel 0 or 1 interrupt */
IRQN_TIMER0B_INTERRUPT = 15, /*!< TIMER0 channel 2 or 3 interrupt */
IRQN_TIMER1A_INTERRUPT = 16, /*!< TIMER1 channel 0 or 1 interrupt */
IRQN_TIMER1B_INTERRUPT = 17, /*!< TIMER1 channel 2 or 3 interrupt */
IRQN_TIMER2A_INTERRUPT = 18, /*!< TIMER2 channel 0 or 1 interrupt */
IRQN_TIMER2B_INTERRUPT = 19, /*!< TIMER2 channel 2 or 3 interrupt */
IRQN_RTC_INTERRUPT = 20, /*!< RTC tick and alarm interrupt */
IRQN_WDT0_INTERRUPT = 21, /*!< Watching dog timer0 interrupt */
IRQN_WDT1_INTERRUPT = 22, /*!< Watching dog timer1 interrupt */
IRQN_APB_GPIO_INTERRUPT = 23, /*!< APB GPIO interrupt */
IRQN_DVP_INTERRUPT = 24, /*!< Digital video port interrupt */
IRQN_AI_INTERRUPT = 25, /*!< AI accelerator interrupt */
IRQN_FFT_INTERRUPT = 26, /*!< FFT accelerator interrupt */
IRQN_DMA0_INTERRUPT = 27, /*!< DMA channel0 interrupt */
IRQN_DMA1_INTERRUPT = 28, /*!< DMA channel1 interrupt */
IRQN_DMA2_INTERRUPT = 29, /*!< DMA channel2 interrupt */
IRQN_DMA3_INTERRUPT = 30, /*!< DMA channel3 interrupt */
IRQN_DMA4_INTERRUPT = 31, /*!< DMA channel4 interrupt */
IRQN_DMA5_INTERRUPT = 32, /*!< DMA channel5 interrupt */
IRQN_UARTHS_INTERRUPT = 4, /*!< Hi-speed UART0 interrupt */
IRQN_GPIOHS0_INTERRUPT = 34, /*!< Hi-speed GPIO0 interrupt */
IRQN_GPIOHS1_INTERRUPT = 35, /*!< Hi-speed GPIO1 interrupt */
IRQN_GPIOHS2_INTERRUPT = 36, /*!< Hi-speed GPIO2 interrupt */
IRQN_GPIOHS3_INTERRUPT = 37, /*!< Hi-speed GPIO3 interrupt */
IRQN_GPIOHS4_INTERRUPT = 38, /*!< Hi-speed GPIO4 interrupt */
IRQN_GPIOHS5_INTERRUPT = 39, /*!< Hi-speed GPIO5 interrupt */
IRQN_GPIOHS6_INTERRUPT = 40, /*!< Hi-speed GPIO6 interrupt */
IRQN_GPIOHS7_INTERRUPT = 41, /*!< Hi-speed GPIO7 interrupt */
IRQN_GPIOHS8_INTERRUPT = 42, /*!< Hi-speed GPIO8 interrupt */
IRQN_GPIOHS9_INTERRUPT = 43, /*!< Hi-speed GPIO9 interrupt */
IRQN_GPIOHS10_INTERRUPT = 44, /*!< Hi-speed GPIO10 interrupt */
IRQN_GPIOHS11_INTERRUPT = 45, /*!< Hi-speed GPIO11 interrupt */
IRQN_GPIOHS12_INTERRUPT = 46, /*!< Hi-speed GPIO12 interrupt */
IRQN_GPIOHS13_INTERRUPT = 47, /*!< Hi-speed GPIO13 interrupt */
IRQN_GPIOHS14_INTERRUPT = 48, /*!< Hi-speed GPIO14 interrupt */
IRQN_GPIOHS15_INTERRUPT = 49, /*!< Hi-speed GPIO15 interrupt */
IRQN_GPIOHS16_INTERRUPT = 50, /*!< Hi-speed GPIO16 interrupt */
IRQN_GPIOHS17_INTERRUPT = 51, /*!< Hi-speed GPIO17 interrupt */
IRQN_GPIOHS18_INTERRUPT = 52, /*!< Hi-speed GPIO18 interrupt */
IRQN_GPIOHS19_INTERRUPT = 53, /*!< Hi-speed GPIO19 interrupt */
IRQN_GPIOHS20_INTERRUPT = 54, /*!< Hi-speed GPIO20 interrupt */
IRQN_GPIOHS21_INTERRUPT = 55, /*!< Hi-speed GPIO21 interrupt */
IRQN_GPIOHS22_INTERRUPT = 56, /*!< Hi-speed GPIO22 interrupt */
IRQN_GPIOHS23_INTERRUPT = 57, /*!< Hi-speed GPIO23 interrupt */
IRQN_GPIOHS24_INTERRUPT = 58, /*!< Hi-speed GPIO24 interrupt */
IRQN_GPIOHS25_INTERRUPT = 59, /*!< Hi-speed GPIO25 interrupt */
IRQN_GPIOHS26_INTERRUPT = 60, /*!< Hi-speed GPIO26 interrupt */
IRQN_GPIOHS27_INTERRUPT = 61, /*!< Hi-speed GPIO27 interrupt */
IRQN_GPIOHS28_INTERRUPT = 62, /*!< Hi-speed GPIO28 interrupt */
IRQN_GPIOHS29_INTERRUPT = 63, /*!< Hi-speed GPIO29 interrupt */
IRQN_GPIOHS30_INTERRUPT = 64, /*!< Hi-speed GPIO30 interrupt */
IRQN_GPIOHS31_INTERRUPT = 65, /*!< Hi-speed GPIO31 interrupt */
IRQN_MAX
} plic_irq_t;
/* clang-format on */
/**
* @brief Interrupt Source Priorities
*
* Each external interrupt source can be assigned a priority by
* writing to its 32-bit memory-mapped priority register. The
* number and value of supported priority levels can vary by
* implementa- tion, with the simplest implementations having all
* devices hardwired at priority 1, in which case, interrupts with
* the lowest ID have the highest effective priority. The priority
* registers are all WARL.
*/
typedef struct _plic_source_priorities
{
/* 0x0C000000: Reserved, 0x0C000004-0x0C000FFC: 1-1023 priorities */
uint32_t priority[1024];
} __attribute__((packed, aligned(4))) plic_source_priorities_t;
/**
* @brief Interrupt Pending Bits
*
* The current status of the interrupt source pending bits in the
* PLIC core can be read from the pending array, organized as 32
* words of 32 bits. The pending bit for interrupt ID N is stored
* in bit (N mod 32) of word (N/32). Bit 0 of word 0, which
* represents the non-existent interrupt source 0, is always
* hardwired to zero. The pending bits are read-only. A pending
* bit in the PLIC core can be cleared by setting enable bits to
* only enable the desired interrupt, then performing a claim. A
* pending bit can be set by instructing the associated gateway to
* send an interrupt service request.
*/
typedef struct _plic_pending_bits
{
/* 0x0C001000-0x0C00107C: Bit 0 is zero, Bits 1-1023 is pending bits */
uint32_t u32[32];
/* 0x0C001080-0x0C001FFF: Reserved */
uint8_t resv[0xF80];
} __attribute__((packed, aligned(4))) plic_pending_bits_t;
/**
* @brief Target Interrupt Enables
*
* For each interrupt target, each devices interrupt can be
* enabled by setting the corresponding bit in that targets
* enables registers. The enables for a target are accessed as a
* contiguous array of 32×32-bit words, packed the same way as the
* pending bits. For each target, bit 0 of enable word 0
* represents the non-existent interrupt ID 0 and is hardwired to
* 0. Unused interrupt IDs are also hardwired to zero. The enables
* arrays for different targets are packed contiguously in the
* address space. Only 32-bit word accesses are supported by the
* enables array in RV32 systems. Implementations can trap on
* accesses to enables for non-existent targets, but must allow
* access to the full enables array for any extant target,
* treating all non-existent interrupt sources enables as
* hardwired to zero.
*/
typedef struct _plic_target_enables
{
/* 0x0C002000-0x0C1F1F80: target 0-15871 enables */
struct
{
uint32_t enable[32 * 2];/* Offset 0x00-0x7C: Bit 0 is zero, Bits 1-1023 is bits*/
} target[15872 / 2];
/* 0x0C1F2000-0x0C1FFFFC: Reserved, size 0xE000 */
uint8_t resv[0xE000];
} __attribute__((packed, aligned(4))) plic_target_enables_t;
/**
* @brief PLIC Targets
*
* Target Priority Thresholds The threshold for a pending
* interrupt priority that can interrupt each target can be set in
* the targets threshold register. The threshold is a WARL field,
* where different implementations can support different numbers
* of thresholds. The simplest implementation has a threshold
* hardwired to zero.
*
* Target Claim Each target can perform a claim by reading the
* claim/complete register, which returns the ID of the highest
* priority pending interrupt or zero if there is no pending
* interrupt for the target. A successful claim will also
* atomically clear the corresponding pending bit on the interrupt
* source. A target can perform a claim at any time, even if the
* EIP is not set. The claim operation is not affected by the
* setting of the targets priority threshold register.
*
* Target Completion A target signals it has completed running a
* handler by writing the interrupt ID it received from the claim
* to the claim/complete register. This is routed to the
* corresponding interrupt gateway, which can now send another
* interrupt request to the PLIC. The PLIC does not check whether
* the completion ID is the same as the last claim ID for that
* target. If the completion ID does not match an interrupt source
* that is currently enabled for the target, the completion is
* silently ignored.
*/
typedef struct _plic_target
{
/* 0x0C200000-0x0FFFF004: target 0-15871 */
struct {
uint32_t priority_threshold;/* Offset 0x000 */
uint32_t claim_complete; /* Offset 0x004 */
uint8_t resv[0x1FF8]; /* Offset 0x008, Size 0xFF8 */
} target[15872 / 2];
} __attribute__((packed, aligned(4))) plic_target_t;
/**
* @brief Platform-Level Interrupt Controller
*
* PLIC is Platform-Level Interrupt Controller. The PLIC complies
* with the RISC-V Privileged Architecture specification, and can
* support a maximum of 1023 external interrupt sources targeting
* up to 15,872 core contexts.
*/
typedef struct _plic
{
/* 0x0C000000-0x0C000FFC */
plic_source_priorities_t source_priorities;
/* 0x0C001000-0x0C001FFF */
const plic_pending_bits_t pending_bits;
/* 0x0C002000-0x0C1FFFFC */
plic_target_enables_t target_enables;
/* 0x0C200000-0x0FFFF004 */
plic_target_t targets;
} __attribute__((packed, aligned(4))) plic_t;
extern volatile plic_t *const plic;
/**
* @brief Definitions for the interrupt callbacks
*/
typedef int (*plic_irq_callback_t)(void *ctx);
/**
* @brief Definitions for IRQ table instance
*/
typedef struct _plic_instance_t
{
plic_irq_callback_t callback;
void *ctx;
} plic_instance_t;
typedef struct _plic_callback_t
{
plic_irq_callback_t callback;
void *ctx;
uint32_t priority;
} plic_interrupt_t;
/**
* @brief Initialize PLIC external interrupt
*
* @note This function will set MIP_MEIP. The MSTATUS_MIE must set by user.
*
* @return result
* - 0 Success
* - Other Fail
*/
void plic_init(void);
/**
* @brief Enable PLIC external interrupt
*
* @param[in] irq_number external interrupt number
*
* @return result
* - 0 Success
* - Other Fail
*/
int plic_irq_enable(plic_irq_t irq_number);
/**
* @brief Disable PLIC external interrupt
*
* @param[in] irq_number The external interrupt number
*
* @return result
* - 0 Success
* - Other Fail
*/
int plic_irq_disable(plic_irq_t irq_number);
/**
* @brief Set IRQ priority
*
* @param[in] irq_number The external interrupt number
* @param[in] priority The priority of external interrupt number
*
* @return result
* - 0 Success
* - Other Fail
*/
int plic_set_priority(plic_irq_t irq_number, uint32_t priority);
/**
* @brief Get IRQ priority
*
* @param[in] irq_number The external interrupt number
*
* @return The priority of external interrupt number
*/
uint32_t plic_get_priority(plic_irq_t irq_number);
/**
* @brief Claim an IRQ
*
* @return The current IRQ number
*/
uint32_t plic_irq_claim(void);
/**
* @brief Complete an IRQ
*
* @param[in] source The source IRQ number to complete
*
* @return result
* - 0 Success
* - Other Fail
*/
int plic_irq_complete(uint32_t source);
/**
* @brief Register user callback function by IRQ number
*
* @param[in] irq The irq
* @param[in] callback The callback
* @param ctx The context
*
* @return result
* - 0 Success
* - Other Fail
*/
void plic_irq_register(plic_irq_t irq, plic_irq_callback_t callback, void *ctx);
/**
* @brief Deegister user callback function by IRQ number
*
* @param[in] irq The irq
*
* @return result
* - 0 Success
* - Other Fail
*/
void plic_irq_deregister(plic_irq_t irq);
/**
* @brief Deegister user callback function by IRQ number
*
* @param[in] irq The irq
*
* @return result
* - 0 Success
* - Other Fail
*/
void plic_irq_unregister(plic_irq_t irq);
/**
* @brief Get IRQ table, Usage:
* plic_instance_t (*plic_instance)[IRQN_MAX] = plic_get_instance();
* ... plic_instance[x][y] ...;
*
* @return the point of IRQ table
*/
plic_instance_t (*plic_get_instance(void))[IRQN_MAX];
/* For c++ compatibility */
#ifdef __cplusplus
}
#endif
#endif /* __PLIC_H__ */

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,357 @@
/* Copyright 2018 Canaan Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* @file utils.h
* @brief add from Canaan k210 SDK
* https://canaan-creative.com/developer
* @version 1.0
* @author AIIT XUOS Lab
* @date 2021-04-25
*/
#ifndef __UTILS_H__
#define __UTILS_H__
#ifdef __cplusplus
#include <cstdbool>
#include <cstddef>
#include <cstdint>
#else /* __cplusplus */
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#include <stdio.h>
#endif /* __cplusplus */
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
#define KENDRYTE_MIN(a, b) ((a) > (b) ? (b) : (a))
#define KENDRYTE_MAX(a, b) ((a) > (b) ? (a) : (b))
#ifdef __ASSEMBLY__
#define KENDRYTE_CAST(type, ptr) ptr
#else /* __ASSEMBLY__ */
/**
* @brief Cast the pointer to specified pointer type.
*
* @param[in] type The pointer type to cast to
* @param[in] ptr The pointer to apply the type cast to
*/
#define KENDRYTE_CAST(type, ptr) ((type)(ptr))
#endif /* __ASSEMBLY__ */
/**
* @addtogroup UTIL_RW_FUNC Memory Read/Write Utilities
*
* This section implements read and write functionality for various
* memory untis. The memory unit terms used for these functions are
* consistent with those used in the ARM Architecture Reference Manual
* ARMv7-A and ARMv7-R edition manual. The terms used for units of memory are:
*
* Unit of Memory | Abbreviation | Size in Bits
* :---------------|:-------------|:------------:
* Byte | byte | 8
* Half Word | hword | 16
* Word | word | 32
* Double Word | dword | 64
*
*/
/**
* @brief Write the 8 bit byte to the destination address in device memory.
*
* @param[in] dest Write destination pointer address
* @param[in] src 8 bit data byte to write to memory
*/
#define kendryte_write_byte(dest, src) \
(*KENDRYTE_CAST(volatile uint8_t*, (dest)) = (src))
/**
* @brief Read and return the 8 bit byte from the source address in device memory.
*
* @param[in] src Read source pointer address
*
* @return 8 bit data byte value
*/
#define kendryte_read_byte(src) (*KENDRYTE_CAST(volatile uint8_t*, (src)))
/**
* @brief Write the 16 bit half word to the destination address in device memory.
*
* @param[in] dest Write destination pointer address
* @param[in] src 16 bit data half word to write to memory
*/
#define kendryte_write_hword(dest, src) \
(*KENDRYTE_CAST(volatile uint16_t*, (dest)) = (src))
/**
* @brief Read and return the 16 bit half word from the source address in device
*
* @param[in] src Read source pointer address
*
* @return 16 bit data half word value
*/
#define kendryte_read_hword(src) (*KENDRYTE_CAST(volatile uint16_t*, (src)))
/**
* @brief Write the 32 bit word to the destination address in device memory.
*
* @param[in] dest Write destination pointer address
* @param[in] src 32 bit data word to write to memory
*/
#define kendryte_write_word(dest, src) \
(*KENDRYTE_CAST(volatile uint32_t*, (dest)) = (src))
/**
* @brief Read and return the 32 bit word from the source address in device memory.
*
* @param[in] src Read source pointer address
*
* @return 32 bit data half word value
*/
#define kendryte_read_word(src) (*KENDRYTE_CAST(volatile uint32_t*, (src)))
/**
* @brief Write the 64 bit double word to the destination address in device memory.
*
* @param[in] dest Write destination pointer address
* @param[in] src 64 bit data word to write to memory
*/
#define kendryte_write_dword(dest, src) \
(*KENDRYTE_CAST(volatile uint64_t*, (dest)) = (src))
/**
* @brief Read and return the 64 bit double word from the source address in device
*
* @param[in] src Read source pointer address
*
* @return 64 bit data half word value
*/
#define kendryte_read_dword(src) (*KENDRYTE_CAST(volatile uint64_t*, (src)))
/**
* @brief Set selected bits in the 8 bit byte at the destination address in device
*
* @param[in] dest Destination pointer address
* @param[in] bits Bits to set in destination byte
*/
#define kendryte_setbits_byte(dest, bits) \
(kendryte_write_byte(dest, kendryte_read_byte(dest) | (bits)))
/**
* @brief Clear selected bits in the 8 bit byte at the destination address in device
*
* @param[in] dest Destination pointer address
* @param[in] bits Bits to clear in destination byte
*/
#define kendryte_clrbits_byte(dest, bits) \
(kendryte_write_byte(dest, kendryte_read_byte(dest) & ~(bits)))
/**
* @brief Change or toggle selected bits in the 8 bit byte at the destination address
*
* @param[in] dest Destination pointer address
* @param[in] bits Bits to change in destination byte
*/
#define kendryte_xorbits_byte(dest, bits) \
(kendryte_write_byte(dest, kendryte_read_byte(dest) ^ (bits)))
/**
* @brief Replace selected bits in the 8 bit byte at the destination address in device
*
* @param[in] dest Destination pointer address
* @param[in] msk Bits to replace in destination byte
* @param[in] src Source bits to write to cleared bits in destination byte
*/
#define kendryte_replbits_byte(dest, msk, src) \
(kendryte_write_byte(dest, (kendryte_read_byte(dest) & ~(msk)) | ((src) & (msk))))
/**
* @brief Set selected bits in the 16 bit halfword at the destination address in
*
* @param[in] dest Destination pointer address
* @param[in] bits Bits to set in destination halfword
*/
#define kendryte_setbits_hword(dest, bits) \
(kendryte_write_hword(dest, kendryte_read_hword(dest) | (bits)))
/**
* @brief Clear selected bits in the 16 bit halfword at the destination address in
*
* @param[in] dest Destination pointer address
* @param[in] bits Bits to clear in destination halfword
*/
#define kendryte_clrbits_hword(dest, bits) \
(kendryte_write_hword(dest, kendryte_read_hword(dest) & ~(bits)))
/**
* @brief Change or toggle selected bits in the 16 bit halfword at the destination
*
* @param[in] dest Destination pointer address
* @param[in] bits Bits to change in destination halfword
*/
#define kendryte_xorbits_hword(dest, bits) \
(kendryte_write_hword(dest, kendryte_read_hword(dest) ^ (bits)))
/**
* @brief Replace selected bits in the 16 bit halfword at the destination address in
*
* @param[in] dest Destination pointer address
* @param[in] msk Bits to replace in destination byte
* @param[in] src Source bits to write to cleared bits in destination halfword
*/
#define kendryte_replbits_hword(dest, msk, src) \
(kendryte_write_hword(dest, (kendryte_read_hword(dest) & ~(msk)) | ((src) & (msk))))
/**
* @brief Set selected bits in the 32 bit word at the destination address in device
*
* @param[in] dest Destination pointer address
* @param[in] bits Bits to set in destination word
*/
#define kendryte_setbits_word(dest, bits) \
(kendryte_write_word(dest, kendryte_read_word(dest) | (bits)))
/**
* @brief Clear selected bits in the 32 bit word at the destination address in device
*
* @param[in] dest Destination pointer address
* @param[in] bits Bits to clear in destination word
*/
#define kendryte_clrbits_word(dest, bits) \
(kendryte_write_word(dest, kendryte_read_word(dest) & ~(bits)))
/**
* @brief Change or toggle selected bits in the 32 bit word at the destination address
*
* @param[in] dest Destination pointer address
* @param[in] bits Bits to change in destination word
*/
#define kendryte_xorbits_word(dest, bits) \
(kendryte_write_word(dest, kendryte_read_word(dest) ^ (bits)))
/**
* @brief Replace selected bits in the 32 bit word at the destination address in
*
* @param[in] dest Destination pointer address
* @param[in] msk Bits to replace in destination word
* @param[in] src Source bits to write to cleared bits in destination word
*/
#define kendryte_replbits_word(dest, msk, src) \
(kendryte_write_word(dest, (kendryte_read_word(dest) & ~(msk)) | ((src) & (msk))))
/**
* @brief Set selected bits in the 64 bit doubleword at the destination address in
*
* @param[in] dest Destination pointer address
* @param[in] bits Bits to set in destination doubleword
*/
#define kendryte_setbits_dword(dest, bits) \
(kendryte_write_dword(dest, kendryte_read_dword(dest) | (bits)))
/**
* @brief Clear selected bits in the 64 bit doubleword at the destination address in
*
* @param[in] dest Destination pointer address
* @param[in] bits Bits to clear in destination doubleword
*/
#define kendryte_clrbits_dword(dest, bits) \
(kendryte_write_dword(dest, kendryte_read_dword(dest) & ~(bits)))
/**
* @brief Change or toggle selected bits in the 64 bit doubleword at the destination
*
* @param[in] dest Destination pointer address
* @param[in] bits Bits to change in destination doubleword
*/
#define kendryte_xorbits_dword(dest, bits) \
(kendryte_write_dword(dest, kendryte_read_dword(dest) ^ (bits)))
/**
* @brief Replace selected bits in the 64 bit doubleword at the destination address in
*
* @param[in] dest Destination pointer address
* @param[in] msk its to replace in destination doubleword
* @param[in] src Source bits to write to cleared bits in destination word
*/
#define kendryte_replbits_dword(dest, msk, src) \
(kendryte_write_dword(dest, (kendryte_read_dword(dest) & ~(msk)) | ((src) & (msk))))
#define configASSERT(x) \
if ((x) == 0) \
{ \
printf("(%s:%d) %s\r\n", __FILE__, __LINE__, #x); \
for (;;) \
; \
}
/**
* @brief Set value by mask
*
* @param[in] bits The one be set
* @param[in] mask mask value
* @param[in] value The value to set
*/
void set_bit(volatile uint32_t *bits, uint32_t mask, uint32_t value);
/**
* @brief Set value by mask
*
* @param[in] bits The one be set
* @param[in] mask Mask value
* @param[in] offset Mask's offset
* @param[in] value The value to set
*/
void set_bit_offset(volatile uint32_t *bits, uint32_t mask, size_t offset, uint32_t value);
/**
* @brief Set bit for gpio, only set one bit
*
* @param[in] bits The one be set
* @param[in] idx Offset value
* @param[in] value The value to set
*/
void set_gpio_bit(volatile uint32_t *bits, size_t idx, uint32_t value);
/**
* @brief Get bits value of mask
*
* @param[in] bits The source data
* @param[in] mask Mask value
* @param[in] offset Mask's offset
*
* @return The bits value of mask
*/
uint32_t get_bit(volatile uint32_t *bits, uint32_t mask, size_t offset);
/**
* @brief Get a bit value by offset
*
* @param[in] bits The source data
* @param[in] offset Bit's offset
*
*
* @return The bit value
*/
uint32_t get_gpio_bit(volatile uint32_t *bits, size_t offset);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* _DRIVER_COMMON_H */

View File

@ -0,0 +1,180 @@
/* Copyright 2018 Canaan Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* @file wdt.h
* @brief add from Canaan k210 SDK
* https://canaan-creative.com/developer
* @version 1.0
* @author AIIT XUOS Lab
* @date 2021-04-25
*/
#ifndef __WDT_H__
#define __WDT_H__
#include <stdint.h>
#include <stddef.h>
#include <plic.h>
#ifdef __cplusplus
extern "C" {
#endif
/* clang-format off */
typedef struct _wdt
{
/* WDT Control Register (0x00) */
volatile uint32_t cr;
/* WDT Timeout Range Register (0x04) */
volatile uint32_t torr;
/* WDT Current Counter Value Register (0x08) */
volatile uint32_t ccvr;
/* WDT Counter Restart Register (0x0c) */
volatile uint32_t crr;
/* WDT Interrupt Status Register (0x10) */
volatile uint32_t stat;
/* WDT Interrupt Clear Register (0x14) */
volatile uint32_t eoi;
/* reserverd (0x18) */
volatile uint32_t resv1;
/* WDT Protection level Register (0x1c) */
volatile uint32_t prot_level;
/* reserved (0x20-0xe0) */
volatile uint32_t resv4[49];
/* WDT Component Parameters Register 5 (0xe4) */
volatile uint32_t comp_param_5;
/* WDT Component Parameters Register 4 (0xe8) */
volatile uint32_t comp_param_4;
/* WDT Component Parameters Register 3 (0xec) */
volatile uint32_t comp_param_3;
/* WDT Component Parameters Register 2 (0xf0) */
volatile uint32_t comp_param_2;
/* WDT Component Parameters Register 1 (0xf4) */
volatile uint32_t comp_param_1;
/* WDT Component Version Register (0xf8) */
volatile uint32_t comp_version;
/* WDT Component Type Register (0xfc) */
volatile uint32_t comp_type;
} __attribute__((packed, aligned(4))) wdt_t;
typedef enum _wdt_device_number
{
WDT_DEVICE_0,
WDT_DEVICE_1,
WDT_DEVICE_MAX,
} wdt_device_number_t;
#define WDT_RESET_ALL 0x00000000U
#define WDT_RESET_CPU 0x00000001U
/* WDT Control Register */
#define WDT_CR_ENABLE 0x00000001U
#define WDT_CR_RMOD_MASK 0x00000002U
#define WDT_CR_RMOD_RESET 0x00000000U
#define WDT_CR_RMOD_INTERRUPT 0x00000002U
#define WDT_CR_RPL_MASK 0x0000001CU
#define WDT_CR_RPL(x) ((x) << 2)
/* WDT Timeout Range Register */
#define WDT_TORR_TOP_MASK 0x000000FFU
#define WDT_TORR_TOP(x) ((x) << 4 | (x) << 0)
/* WDT Current Counter Value Register */
#define WDT_CCVR_MASK 0xFFFFFFFFU
/* WDT Counter Restart Register */
#define WDT_CRR_MASK 0x00000076U
/* WDT Interrupt Status Register */
#define WDT_STAT_MASK 0x00000001U
/* WDT Interrupt Clear Register */
#define WDT_EOI_MASK 0x00000001U
/* WDT Protection level Register */
#define WDT_PROT_LEVEL_MASK 0x00000007U
/* WDT Component Parameter Register 5 */
#define WDT_COMP_PARAM_5_CP_WDT_USER_TOP_MAX_MASK 0xFFFFFFFFU
/* WDT Component Parameter Register 4 */
#define WDT_COMP_PARAM_4_CP_WDT_USER_TOP_INIT_MAX_MASK 0xFFFFFFFFU
/* WDT Component Parameter Register 3 */
#define WDT_COMP_PARAM_3_CD_WDT_TOP_RST_MASK 0xFFFFFFFFU
/* WDT Component Parameter Register 2 */
#define WDT_COMP_PARAM_3_CP_WDT_CNT_RST_MASK 0xFFFFFFFFU
/* WDT Component Parameter Register 1 */
#define WDT_COMP_PARAM_1_WDT_ALWAYS_EN_MASK 0x00000001U
#define WDT_COMP_PARAM_1_WDT_DFLT_RMOD_MASK 0x00000002U
#define WDT_COMP_PARAM_1_WDT_DUAL_TOP_MASK 0x00000004U
#define WDT_COMP_PARAM_1_WDT_HC_RMOD_MASK 0x00000008U
#define WDT_COMP_PARAM_1_WDT_HC_RPL_MASK 0x00000010U
#define WDT_COMP_PARAM_1_WDT_HC_TOP_MASK 0x00000020U
#define WDT_COMP_PARAM_1_WDT_USE_FIX_TOP_MASK 0x00000040U
#define WDT_COMP_PARAM_1_WDT_PAUSE_MASK 0x00000080U
#define WDT_COMP_PARAM_1_APB_DATA_WIDTH_MASK 0x00000300U
#define WDT_COMP_PARAM_1_WDT_DFLT_RPL_MASK 0x00001C00U
#define WDT_COMP_PARAM_1_WDT_DFLT_TOP_MASK 0x000F0000U
#define WDT_COMP_PARAM_1_WDT_DFLT_TOP_INIT_MASK 0x00F00000U
#define WDT_COMP_PARAM_1_WDT_CNT_WIDTH_MASK 0x1F000000U
/* WDT Component Version Register */
#define WDT_COMP_VERSION_MASK 0xFFFFFFFFU
/* WDT Component Type Register */
#define WDT_COMP_TYPE_MASK 0xFFFFFFFFU
/* clang-format on */
/**
* @brief Feed wdt
*/
void wdt_feed(wdt_device_number_t id);
/**
* @brief Start wdt
*
* @param[in] id Wdt id 0 or 1
* @param[in] time_out_ms Wdt trigger time
* @param[in] on_irq Wdt interrupt callback
*
*/
void wdt_start(wdt_device_number_t id, uint64_t time_out_ms, plic_irq_callback_t on_irq);
/**
* @brief Start wdt
*
* @param[in] id Wdt id 0 or 1
* @param[in] time_out_ms Wdt trigger time
* @param[in] on_irq Wdt interrupt callback
* @param[in] ctx Param of callback
*
* @return Wdt time
*
*/
uint32_t wdt_init(wdt_device_number_t id, uint64_t time_out_ms, plic_irq_callback_t on_irq, void *ctx);
/**
* @brief Stop wdt
*
* @param[in] id Wdt id 0 or 1
*
*/
void wdt_stop(wdt_device_number_t id);
/**
* @brief Clear wdt interrupt
*
* @param[in] id Wdt id 0 or 1
*
*/
void wdt_clear_interrupt(wdt_device_number_t id);
#ifdef __cplusplus
}
#endif
#endif /* __WDT_H__ */

View File

@ -0,0 +1 @@

View File

@ -0,0 +1,5 @@
SRC_FILES := drv_interrupt.c plic.c clint.c
include $(KERNEL_ROOT)/compiler.mk

View File

@ -0,0 +1,229 @@
/* Copyright 2018 Canaan Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* @file clint.c
* @brief add from Canaan k210 SDK
* https://canaan-creative.com/developer
* @version 1.0
* @author AIIT XUOS Lab
* @date 2021-04-25
*/
#include <stddef.h>
#include <stdint.h>
#include "encoding.h"
#include "clint.h"
#include "sysctl.h"
volatile clint_t* const clint = (volatile clint_t*)CLINT_BASE_ADDR;
static clint_timer_instance_t clint_timer_instance[CLINT_NUM_CORES];
static clint_ipi_instance_t clint_ipi_instance[CLINT_NUM_CORES];
uint64_t clint_get_time(void)
{
/* No difference on cores */
return clint->mtime;
}
int clint_timer_init(void)
{
/* Read core id */
unsigned long core_id = current_coreid();
/* Clear the Machine-Timer bit in MIE */
CLEAR_CSR(mie, MIP_MTIP);
/* Fill core's instance with original data */
/* clang-format off */
clint_timer_instance[core_id] = (const clint_timer_instance_t)
{
.interval = 0,
.cycles = 0,
.single_shot = 0,
.callback = NULL,
.ctx = NULL,
};
/* clang-format on */
return 0;
}
int clint_timer_stop(void)
{
/* Clear the Machine-Timer bit in MIE */
CLEAR_CSR(mie, MIP_MTIP);
return 0;
}
uint64_t clint_timer_get_freq(void)
{
/* The clock is divided by CLINT_CLOCK_DIV */
return SysctlClockGetFreq(SYSCTL_CLOCK_CPU) / CLINT_CLOCK_DIV;
}
int clint_timer_start(uint64_t interval, int single_shot)
{
/* Read core id */
unsigned long core_id = current_coreid();
/* Set timer interval */
if (clint_timer_set_interval(interval) != 0)
return -1;
/* Set timer single shot */
if (clint_timer_set_single_shot(single_shot) != 0)
return -1;
/* Check settings to prevent interval is 0 */
if (clint_timer_instance[core_id].interval == 0)
return -1;
/* Check settings to prevent cycles is 0 */
if (clint_timer_instance[core_id].cycles == 0)
return -1;
/* Add cycle interval to mtimecmp */
uint64_t now = clint->mtime;
uint64_t then = now + clint_timer_instance[core_id].cycles;
/* Set mtimecmp by core id */
clint->mtimecmp[core_id] = then;
/* Enable interrupts in general */
SET_CSR(mstatus, MSTATUS_MIE);
/* Enable the Machine-Timer bit in MIE */
SET_CSR(mie, MIP_MTIP);
return 0;
}
uint64_t clint_timer_get_interval(void)
{
/* Read core id */
unsigned long core_id = current_coreid();
return clint_timer_instance[core_id].interval;
}
int clint_timer_set_interval(uint64_t interval)
{
/* Read core id */
unsigned long core_id = current_coreid();
/* Check parameter */
if (interval == 0)
return -1;
/* Assign user interval with Millisecond(ms) */
clint_timer_instance[core_id].interval = interval;
/* Convert interval to cycles */
clint_timer_instance[core_id].cycles = interval * clint_timer_get_freq() / 1000ULL;
return 0;
}
int clint_timer_get_single_shot(void)
{
/* Read core id */
unsigned long core_id = current_coreid();
/* Get single shot mode by core id */
return clint_timer_instance[core_id].single_shot;
}
int clint_timer_set_single_shot(int single_shot)
{
/* Read core id */
unsigned long core_id = current_coreid();
/* Set single shot mode by core id */
clint_timer_instance[core_id].single_shot = single_shot;
return 0;
}
int clint_timer_register(clint_timer_callback_t callback, void *ctx)
{
/* Read core id */
unsigned long core_id = current_coreid();
/* Set user callback function */
clint_timer_instance[core_id].callback = callback;
/* Assign user context */
clint_timer_instance[core_id].ctx = ctx;
return 0;
}
int clint_timer_unregister(void)
{
/* Just assign NULL to user callback function and context */
return clint_timer_register(NULL, NULL);
}
int clint_ipi_init(void)
{
/* Read core id */
unsigned long core_id = current_coreid();
/* Clear the Machine-Software bit in MIE */
CLEAR_CSR(mie, MIP_MSIP);
/* Fill core's instance with original data */
/* clang-format off */
clint_ipi_instance[core_id] = (const clint_ipi_instance_t){
.callback = NULL,
.ctx = NULL,
};
/* clang-format on */
return 0;
}
int clint_ipi_enable(void)
{
/* Enable interrupts in general */
SET_CSR(mstatus, MSTATUS_MIE);
/* Set the Machine-Software bit in MIE */
SET_CSR(mie, MIP_MSIP);
return 0;
}
int clint_ipi_disable(void)
{
/* Clear the Machine-Software bit in MIE */
CLEAR_CSR(mie, MIP_MSIP);
return 0;
}
int clint_ipi_send(size_t core_id)
{
if (core_id >= CLINT_NUM_CORES)
return -1;
clint->msip[core_id].msip = 1;
return 0;
}
int clint_ipi_clear(size_t core_id)
{
if (core_id >= CLINT_NUM_CORES)
return -1;
if (clint->msip[core_id].msip)
{
clint->msip[core_id].msip = 0;
return 1;
}
return 0;
}
int clint_ipi_register(clint_ipi_callback_t callback, void *ctx)
{
/* Read core id */
unsigned long core_id = current_coreid();
/* Set user callback function */
clint_ipi_instance[core_id].callback = callback;
/* Assign user context */
clint_ipi_instance[core_id].ctx = ctx;
return 0;
}
int clint_ipi_unregister(void)
{
/* Just assign NULL to user callback function and context */
return clint_ipi_register(NULL, NULL);
}

View File

@ -0,0 +1,41 @@
/* Copyright 2018 Canaan Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* @file drv_interrupt.c
* @brief add from Canaan k210 SDK
* https://canaan-creative.com/developer
* @version 1.0
* @author AIIT XUOS Lab
* @date 2021-04-25
*/
#include <plic.h>
void PlicIrqHandle(plic_irq_t irq)
{
plic_instance_t (*plic_instance)[IRQN_MAX] = plic_get_instance();
if (plic_instance[0][irq].callback)
{
plic_instance[0][irq].callback(
plic_instance[0][irq].ctx);
}
else if (plic_instance[1][irq].callback)
{
plic_instance[1][irq].callback(
plic_instance[1][irq].ctx);
}
}

View File

@ -0,0 +1,219 @@
/* Copyright 2018 Canaan Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* @file plic.c
* @brief add from Canaan k210 SDK
* https://canaan-creative.com/developer
* @version 1.0
* @author AIIT XUOS Lab
* @date 2021-04-25
*/
#include <stddef.h>
#include <stdint.h>
#include "encoding.h"
#include "plic.h"
#include "syscalls.h"
#include "syslog.h"
volatile plic_t* const plic = (volatile plic_t*)PLIC_BASE_ADDR;
static plic_instance_t plic_instance[PLIC_NUM_CORES][IRQN_MAX];
void plic_init(void)
{
int i = 0;
/* Get current core id */
unsigned long core_id = current_coreid();
/* Disable all interrupts for the current core. */
for (i = 0; i < ((PLIC_NUM_SOURCES + 32u) / 32u); i++)
plic->target_enables.target[core_id].enable[i] = 0;
static uint8_t s_plic_priorities_init_flag = 0;
/* Set priorities to zero. */
if(s_plic_priorities_init_flag == 0)
{
for (i = 0; i < PLIC_NUM_SOURCES; i++)
plic->source_priorities.priority[i] = 0;
s_plic_priorities_init_flag = 1;
}
/* Set the threshold to zero. */
plic->targets.target[core_id].priority_threshold = 0;
/* Clear PLIC instance for every cores */
for (i = 0; i < IRQN_MAX; i++)
{
/* clang-format off */
plic_instance[core_id][i] = (const plic_instance_t){
.callback = NULL,
.ctx = NULL,
};
/* clang-format on */
}
/*
* A successful claim will also atomically clear the corresponding
* pending bit on the interrupt source. A target can perform a claim
* at any time, even if the EIP is not set.
*/
i = 0;
while (plic->targets.target[core_id].claim_complete > 0 && i < 100)
{
/* This loop will clear pending bit on the interrupt source */
i++;
}
/* Enable machine external interrupts. */
SET_CSR(mie, MIP_MEIP);
}
int plic_irq_enable(plic_irq_t irq_number)
{
/* Check parameters */
if (PLIC_NUM_SOURCES < irq_number || 0 > irq_number)
return -1;
unsigned long core_id = current_coreid();
/* Get current enable bit array by IRQ number */
uint32_t current = plic->target_enables.target[core_id].enable[irq_number / 32];
/* Set enable bit in enable bit array */
current |= (uint32_t)1 << (irq_number % 32);
/* Write back the enable bit array */
plic->target_enables.target[core_id].enable[irq_number / 32] = current;
return 0;
}
int plic_irq_disable(plic_irq_t irq_number)
{
/* Check parameters */
if (PLIC_NUM_SOURCES < irq_number || 0 > irq_number)
return -1;
unsigned long core_id = current_coreid();
/* Get current enable bit array by IRQ number */
uint32_t current = plic->target_enables.target[core_id].enable[irq_number / 32];
/* Clear enable bit in enable bit array */
current &= ~((uint32_t)1 << (irq_number % 32));
/* Write back the enable bit array */
plic->target_enables.target[core_id].enable[irq_number / 32] = current;
return 0;
}
int plic_set_priority(plic_irq_t irq_number, uint32_t priority)
{
/* Check parameters */
if (PLIC_NUM_SOURCES < irq_number || 0 > irq_number)
return -1;
/* Set interrupt priority by IRQ number */
plic->source_priorities.priority[irq_number] = priority;
return 0;
}
uint32_t plic_get_priority(plic_irq_t irq_number)
{
/* Check parameters */
if (PLIC_NUM_SOURCES < irq_number || 0 > irq_number)
return 0;
/* Get interrupt priority by IRQ number */
return plic->source_priorities.priority[irq_number];
}
uint32_t plic_irq_claim(void)
{
unsigned long core_id = current_coreid();
/* Perform IRQ claim */
return plic->targets.target[core_id].claim_complete;
}
int plic_irq_complete(uint32_t source)
{
unsigned long core_id = current_coreid();
/* Perform IRQ complete */
plic->targets.target[core_id].claim_complete = source;
return 0;
}
void plic_irq_register(plic_irq_t irq, plic_irq_callback_t callback, void *ctx)
{
/* Read core id */
unsigned long core_id = current_coreid();
/* Set user callback function */
plic_instance[core_id][irq].callback = callback;
/* Assign user context */
plic_instance[core_id][irq].ctx = ctx;
}
void plic_irq_unregister(plic_irq_t irq)
{
/* Just assign NULL to user callback function and context */
plic_irq_register(irq, NULL, NULL);
}
void __attribute__((weak, alias("plic_irq_unregister"))) plic_irq_deregister(plic_irq_t irq);
plic_instance_t (*plic_get_instance(void))[IRQN_MAX]
{
return plic_instance;
}
/*Entry Point for PLIC Interrupt Handler*/
uintptr_t __attribute__((weak))
HandleIrqMExt(uintptr_t cause, uintptr_t epc)
{
/*
* After the highest-priority pending interrupt is claimed by a target
* and the corresponding IP bit is cleared, other lower-priority
* pending interrupts might then become visible to the target, and so
* the PLIC EIP bit might not be cleared after a claim. The interrupt
* handler can check the local meip/heip/seip/ueip bits before exiting
* the handler, to allow more efficient service of other interrupts
* without first restoring the interrupted context and taking another
* interrupt trap.
*/
if (READ_CSR(mip) & MIP_MEIP)
{
/* Get current core id */
uint64_t core_id = current_coreid();
/* Get primitive interrupt enable flag */
uint64_t ie_flag = READ_CSR(mie);
/* Get current IRQ num */
uint32_t int_num = plic->targets.target[core_id].claim_complete;
/* Get primitive IRQ threshold */
uint32_t int_threshold = plic->targets.target[core_id].priority_threshold;
/* Set new IRQ threshold = current IRQ threshold */
plic->targets.target[core_id].priority_threshold = plic->source_priorities.priority[int_num];
/* Disable software interrupt and timer interrupt */
CLEAR_CSR(mie, MIP_MTIP | MIP_MSIP);
/* Enable global interrupt */
SET_CSR(mstatus, MSTATUS_MIE);
if (plic_instance[core_id][int_num].callback)
plic_instance[core_id][int_num].callback(
plic_instance[core_id][int_num].ctx);
/* Perform IRQ complete */
plic->targets.target[core_id].claim_complete = int_num;
/* Disable global interrupt */
CLEAR_CSR(mstatus, MSTATUS_MIE);
/* Set MPIE and MPP flag used to MRET instructions restore MIE flag */
SET_CSR(mstatus, MSTATUS_MPIE | MSTATUS_MPP);
/* Restore primitive interrupt enable flag */
WRITE_CSR(mie, ie_flag);
/* Restore primitive IRQ threshold */
plic->targets.target[core_id].priority_threshold = int_threshold;
}
return epc;
}

View File

@ -0,0 +1,11 @@
if BSP_USING_RTC
config RTC_BUS_NAME
string "rtc bus name"
default "rtc"
config RTC_DRV_NAME
string "rtc bus driver name"
default "rtc_drv"
config RTC_DEVICE_NAME
string "rtc bus device name"
default "rtc_dev"
endif

View File

@ -0,0 +1,3 @@
SRC_FILES := connect_rtc.c hardware_rtc.c
include $(KERNEL_ROOT)/compiler.mk

View File

@ -0,0 +1,184 @@
/*
* Copyright (c) 2020 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
/**
* @file connect_rtc.c
* @brief support kd233-board rtc function and register to bus framework
* @version 1.0
* @author AIIT XUOS Lab
* @date 2021-04-25
*/
#include <stdint.h>
#include <time.h>
#include <stdlib.h>
#include "sysctl.h"
#include "connect_rtc.h"
#include "hardware_rtc.h"
static int GetWeekDay(int year, int month, int day)
{
/* Magic method to get weekday */
int weekday = (day += month < 3 ? year-- : year - 2,
23 * month / 9 + day + 4 + year / 4 - year / 100 + year / 400) % 7;
return weekday;
}
static uint32 RtcConfigure(void *drv, struct BusConfigureInfo *configure_info)
{
NULL_PARAM_CHECK(drv);
struct RtcDriver *rtc_drv = (struct RtcDriver *)drv;
struct RtcDrvConfigureParam *drv_param = (struct RtcDrvConfigureParam *)configure_info->private_data;
int cmd = drv_param->rtc_operation_cmd;
time_t *time = drv_param->time;
switch (cmd)
{
case OPER_RTC_GET_TIME:
{
struct tm ct;
int year,month,day,hour,minute,second;
memset(&ct,0,sizeof(struct tm));
rtc_timer_get(&year, &month, &day, &hour, &minute, &second);
ct.tm_year = year - 1900;
ct.tm_mon = month - 1;
ct.tm_mday = day;
ct.tm_wday = GetWeekDay(year, month, day);
ct.tm_hour = hour;
ct.tm_min = minute;
ct.tm_sec = second;
*time = mktime(&ct);
}
break;
case OPER_RTC_SET_TIME:
{
struct tm *ct;
struct tm tm_new;
x_base lock;
lock = CriticalAreaLock();
ct = localtime(time);
memcpy(&tm_new, ct, sizeof(struct tm));
CriticalAreaUnLock(lock);
sysctl_reset(SYSCTL_RESET_RTC);
sysctl_clock_enable(SYSCTL_CLOCK_RTC);
rtc_protect_set(0);
rtc_timer_set_clock_frequency(SysctlClockGetFreq(SYSCTL_CLOCK_IN0));
rtc_timer_set_clock_count_value(1);
rtc_timer_set_mode(RTC_TIMER_RUNNING);
if (rtc_timer_set(tm_new.tm_year+1900,tm_new.tm_mon+1,tm_new.tm_mday,
tm_new.tm_hour,tm_new.tm_min,tm_new.tm_sec)==-1)
return ERROR;
}
break;
}
return EOK;
}
/*manage the rtc device operations*/
static const struct RtcDevDone dev_done =
{
.open = NONE,
.close = NONE,
.write = NONE,
.read = NONE,
};
static int BoardRtcBusInit(struct RtcBus *rtc_bus, struct RtcDriver *rtc_driver)
{
x_err_t ret = EOK;
/*Init the rtc bus */
ret = RtcBusInit(rtc_bus, RTC_BUS_NAME);
if (EOK != ret) {
KPrintf("HwRtcInit RtcBusInit error %d\n", ret);
return ERROR;
}
/*Init the rtc driver*/
ret = RtcDriverInit(rtc_driver, RTC_DRV_NAME);
if (EOK != ret) {
KPrintf("HwRtcInit RtcDriverInit error %d\n", ret);
return ERROR;
}
/*Attach the rtc driver to the rtc bus*/
ret = RtcDriverAttachToBus(RTC_DRV_NAME, RTC_BUS_NAME);
if (EOK != ret) {
KPrintf("HwRtcInit RtcDriverAttachToBus error %d\n", ret);
return ERROR;
}
return ret;
}
/*Attach the rtc device to the rtc bus*/
static int BoardRtcDevBend(void)
{
x_err_t ret = EOK;
static struct RtcHardwareDevice rtc_device;
memset(&rtc_device, 0, sizeof(struct RtcHardwareDevice));
rtc_device.dev_done = &(dev_done);
ret = RtcDeviceRegister(&rtc_device, NONE, RTC_DEVICE_NAME);
if (EOK != ret) {
KPrintf("HwRtcInit RtcDeviceInit device %s error %d\n", RTC_DEVICE_NAME, ret);
return ERROR;
}
ret = RtcDeviceAttachToBus(RTC_DEVICE_NAME, RTC_BUS_NAME);
if (EOK != ret) {
KPrintf("HwRtcInit RtcDeviceAttachToBus device %s error %d\n", RTC_DEVICE_NAME, ret);
return ERROR;
}
return ret;
}
int HwRtcInit(void)
{
x_err_t ret = EOK;
static struct RtcBus rtc_bus;
memset(&rtc_bus, 0, sizeof(struct RtcBus));
static struct RtcDriver rtc_driver;
memset(&rtc_driver, 0, sizeof(struct RtcDriver));
rtc_driver.configure = &(RtcConfigure);
ret = BoardRtcBusInit(&rtc_bus, &rtc_driver);
if (EOK != ret) {
KPrintf("HwRtcInit error ret %u\n", ret);
return ERROR;
}
ret = BoardRtcDevBend();
if (EOK != ret) {
KPrintf("HwRtcInit error ret %u\n", ret);
return ERROR;
}
rtc_init();
return ret;
}

View File

@ -0,0 +1,597 @@
/* Copyright 2018 Canaan Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* @file hardware_rtc.c
* @brief add from Canaan k210 SDK
* https://canaan-creative.com/developer
* @version 1.0
* @author AIIT XUOS Lab
* @date 2021-04-25
*/
#include <stdint.h>
#include <time.h>
#include <stdlib.h>
#include "encoding.h"
#include "sysctl.h"
#include "hardware_rtc.h"
volatile rtc_t *const rtc = (volatile rtc_t *)RTC_BASE_ADDR;
struct tm rtc_date_time;
void rtc_timer_set_mode(rtc_timer_mode_t timer_mode)
{
rtc_register_ctrl_t register_ctrl = rtc->register_ctrl;
switch (timer_mode)
{
case RTC_TIMER_PAUSE:
register_ctrl.read_enable = 0;
register_ctrl.write_enable = 0;
break;
case RTC_TIMER_RUNNING:
register_ctrl.read_enable = 1;
register_ctrl.write_enable = 0;
break;
case RTC_TIMER_SETTING:
register_ctrl.read_enable = 0;
register_ctrl.write_enable = 1;
break;
default:
register_ctrl.read_enable = 0;
register_ctrl.write_enable = 0;
break;
}
rtc->register_ctrl = register_ctrl;
}
rtc_timer_mode_t rtc_timer_get_mode(void)
{
rtc_register_ctrl_t register_ctrl = rtc->register_ctrl;
rtc_timer_mode_t timer_mode = RTC_TIMER_PAUSE;
if ((!register_ctrl.read_enable) && (!register_ctrl.write_enable))
{
/* RTC_TIMER_PAUSE */
timer_mode = RTC_TIMER_PAUSE;
}
else if ((register_ctrl.read_enable) && (!register_ctrl.write_enable))
{
/* RTC_TIMER_RUNNING */
timer_mode = RTC_TIMER_RUNNING;
}
else if ((!register_ctrl.read_enable) && (register_ctrl.write_enable)) {
/* RTC_TIMER_SETTING */
timer_mode = RTC_TIMER_SETTING;
}
else
{
/* Something is error, reset timer mode */
rtc_timer_set_mode(timer_mode);
}
return timer_mode;
}
static inline int rtc_in_range(int value, int min, int max)
{
return ((value >= min) && (value <= max));
}
int rtc_timer_set_tm(const struct tm *tm)
{
rtc_date_t timer_date;
rtc_time_t timer_time;
rtc_extended_t timer_extended;
if (tm)
{
/*
* Range of tm->tm_sec could be [0,61]
*
* Range of tm->tm_sec allows for a positive leap second. Two
* leap seconds in the same minute are not allowed (the C90
* range 0..61 was a defect)
*/
if (rtc_in_range(tm->tm_sec, 0, 59))
timer_time.second = tm->tm_sec;
else
return -1;
/* Range of tm->tm_min could be [0,59] */
if (rtc_in_range(tm->tm_min, 0, 59))
timer_time.minute = tm->tm_min;
else
return -1;
/* Range of tm->tm_hour could be [0, 23] */
if (rtc_in_range(tm->tm_hour, 0, 23))
timer_time.hour = tm->tm_hour;
else
return -1;
/* Range of tm->tm_mday could be [1, 31] */
if (rtc_in_range(tm->tm_mday, 1, 31))
timer_date.day = tm->tm_mday;
else
return -1;
/*
* Range of tm->tm_mon could be [0, 11]
* But in this RTC, date.month should be [1, 12]
*/
if (rtc_in_range(tm->tm_mon, 0, 11))
timer_date.month = tm->tm_mon + 1;
else
return -1;
/*
* Range of tm->tm_year is the years since 1900
* But in this RTC, year is split into year and century
* In this RTC, century range is [0,31], year range is [0,99]
*/
int human_year = tm->tm_year + 1900;
int rtc_year = human_year % 100;
int rtc_century = human_year / 100;
if (rtc_in_range(rtc_year, 0, 99) &&
rtc_in_range(rtc_century, 0, 31))
{
timer_date.year = rtc_year;
timer_extended.century = rtc_century;
}
else
return -1;
/* Range of tm->tm_wday could be [0, 6] */
if (rtc_in_range(tm->tm_wday, 0, 6))
timer_date.week = tm->tm_wday;
else
return -1;
/* Set RTC mode to timer setting mode */
rtc_timer_set_mode(RTC_TIMER_SETTING);
/* Write value to RTC */
rtc->date = timer_date;
rtc->time = timer_time;
rtc->extended = timer_extended;
/* Get CPU current freq */
unsigned long freq = SysctlClockGetFreq(SYSCTL_CLOCK_CPU);
/* Set threshold to 1/26000000 s */
freq = freq / 26000000;
/* Get current CPU cycle */
unsigned long start_cycle = read_cycle();
/* Wait for 1/26000000 s to sync data */
while (read_cycle() - start_cycle < freq)
continue;
/* Set RTC mode to timer running mode */
rtc_timer_set_mode(RTC_TIMER_RUNNING);
}
return 0;
}
int rtc_timer_set_alarm_tm(const struct tm *tm)
{
rtc_alarm_date_t alarm_date;
rtc_alarm_time_t alarm_time;
if (tm) {
/*
* Range of tm->tm_sec could be [0,61]
*
* Range of tm->tm_sec allows for a positive leap second. Two
* leap seconds in the same minute are not allowed (the C90
* range 0..61 was a defect)
*/
if (rtc_in_range(tm->tm_sec, 0, 59))
alarm_time.second = tm->tm_sec;
else
return -1;
/* Range of tm->tm_min could be [0,59] */
if (rtc_in_range(tm->tm_min, 0, 59))
alarm_time.minute = tm->tm_min;
else
return -1;
/* Range of tm->tm_hour could be [0, 23] */
if (rtc_in_range(tm->tm_hour, 0, 23))
alarm_time.hour = tm->tm_hour;
else
return -1;
/* Range of tm->tm_mday could be [1, 31] */
if (rtc_in_range(tm->tm_mday, 1, 31))
alarm_date.day = tm->tm_mday;
else
return -1;
/*
* Range of tm->tm_mon could be [0, 11]
* But in this RTC, date.month should be [1, 12]
*/
if (rtc_in_range(tm->tm_mon, 0, 11))
alarm_date.month = tm->tm_mon + 1;
else
return -1;
/*
* Range of tm->tm_year is the years since 1900
* But in this RTC, year is split into year and century
* In this RTC, century range is [0,31], year range is [0,99]
*/
int human_year = tm->tm_year + 1900;
int rtc_year = human_year % 100;
int rtc_century = human_year / 100;
if (rtc_in_range(rtc_year, 0, 99) &&
rtc_in_range(rtc_century, 0, 31))
{
alarm_date.year = rtc_year;
} else
return -1;
/* Range of tm->tm_wday could be [0, 6] */
if (rtc_in_range(tm->tm_wday, 0, 6))
alarm_date.week = tm->tm_wday;
else
return -1;
/* Write value to RTC */
rtc->alarm_date = alarm_date;
rtc->alarm_time = alarm_time;
}
return 0;
}
static int rtc_year_is_leap(int year)
{
return (year % 4 == 0 && year % 100 != 0) || (year % 400 == 0);
}
static int rtc_get_yday(int year, int month, int day)
{
static const int days[2][13] =
{
{0, 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334},
{0, 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335}
};
int leap = rtc_year_is_leap(year);
return days[leap][month] + day;
}
static int rtc_get_wday(int year, int month, int day)
{
/* Magic method to get weekday */
int weekday = (day += month < 3 ? year-- : year - 2, 23 * month / 9 + day + 4 + year / 4 - year / 100 + year / 400) % 7;
return weekday;
}
struct tm *rtc_timer_get_tm(void)
{
if (rtc_timer_get_mode() != RTC_TIMER_RUNNING)
return NULL;
rtc_date_t timer_date = rtc->date;
rtc_time_t timer_time = rtc->time;
rtc_extended_t timer_extended = rtc->extended;
struct tm *tm = &rtc_date_time;
tm->tm_sec = timer_time.second % 60;
tm->tm_min = timer_time.minute % 60;
tm->tm_hour = timer_time.hour % 24;
tm->tm_mday = (timer_date.day - 1) % 31 + 1;
tm->tm_mon = (timer_date.month - 1)% 12;
tm->tm_year = (timer_date.year % 100) + (timer_extended.century * 100) - 1900;
tm->tm_wday = timer_date.week;
tm->tm_yday = rtc_get_yday(tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday);
tm->tm_isdst = -1;
return tm;
}
struct tm *rtc_timer_get_alarm_tm(void)
{
if (rtc_timer_get_mode() != RTC_TIMER_RUNNING)
return NULL;
rtc_alarm_date_t alarm_date = rtc->alarm_date;
rtc_alarm_time_t alarm_time = rtc->alarm_time;
rtc_extended_t timer_extended = rtc->extended;
struct tm *tm = &rtc_date_time;
tm->tm_sec = alarm_time.second % 60;
tm->tm_min = alarm_time.minute % 60;
tm->tm_hour = alarm_time.hour % 24;
tm->tm_mday = alarm_date.day % 31;
tm->tm_mon = (alarm_date.month % 12) - 1;
/* Alarm and Timer use same timer_extended.century */
tm->tm_year = (alarm_date.year % 100) + (timer_extended.century * 100) - 1900;
tm->tm_wday = alarm_date.week;
tm->tm_yday = rtc_get_yday(tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday);
tm->tm_isdst = -1;
return tm;
}
int rtc_timer_set(int year, int month, int day, int hour, int minute, int second)
{
struct tm date_time =
{
.tm_sec = second,
.tm_min = minute,
.tm_hour = hour,
.tm_mday = day,
.tm_mon = month - 1,
.tm_year = year - 1900,
.tm_wday = rtc_get_wday(year, month, day),
.tm_yday = rtc_get_yday(year, month, day),
.tm_isdst = -1,
};
return rtc_timer_set_tm(&date_time);
}
int rtc_timer_get(int *year, int *month, int *day, int *hour, int *minute, int *second)
{
struct tm *tm = rtc_timer_get_tm();
if (tm)
{
if (year)
*year = tm->tm_year + 1900;
if (month)
*month = tm->tm_mon + 1;
if (day)
*day = tm->tm_mday;
if (hour)
*hour = tm->tm_hour;
if (minute)
*minute = tm->tm_min;
if (second)
*second = tm->tm_sec;
} else
return -1;
return 0;
}
int rtc_timer_set_alarm(int year, int month, int day, int hour, int minute, int second)
{
struct tm date_time = {
.tm_sec = second,
.tm_min = minute,
.tm_hour = hour,
.tm_mday = day,
.tm_mon = month - 1,
.tm_year = year - 1900,
.tm_wday = rtc_get_wday(year, month, day),
.tm_yday = rtc_get_yday(year, month, day),
.tm_isdst = -1,
};
return rtc_timer_set_alarm_tm(&date_time);
}
int rtc_timer_get_alarm(int *year, int *month, int *day, int *hour, int *minute, int *second)
{
struct tm *tm = rtc_timer_get_alarm_tm();
if (tm) {
if (year)
*year = tm->tm_year + 1900;
if (month)
*month = tm->tm_mon + 1;
if (day)
*day = tm->tm_mday;
if (hour)
*hour = tm->tm_hour;
if (minute)
*minute = tm->tm_min;
if (second)
*second = tm->tm_sec;
} else
return -1;
return 0;
}
int rtc_timer_set_clock_frequency(unsigned int frequency)
{
rtc_initial_count_t initial_count;
initial_count.count = frequency;
rtc_timer_set_mode(RTC_TIMER_SETTING);
rtc->initial_count = initial_count;
rtc_timer_set_mode(RTC_TIMER_RUNNING);
return 0;
}
unsigned int rtc_timer_get_clock_frequency(void)
{
return rtc->initial_count.count;
}
int rtc_timer_set_clock_count_value(unsigned int count)
{
rtc_current_count_t current_count;
current_count.count = count;
rtc_timer_set_mode(RTC_TIMER_SETTING);
rtc->current_count = current_count;
rtc_timer_set_mode(RTC_TIMER_RUNNING);
return 0;
}
unsigned int rtc_timer_get_clock_count_value(void)
{
return rtc->current_count.count;
}
int rtc_tick_interrupt_set(int enable)
{
rtc_interrupt_ctrl_t interrupt_ctrl = rtc->interrupt_ctrl;
interrupt_ctrl.tick_enable = enable;
rtc_timer_set_mode(RTC_TIMER_SETTING);
rtc->interrupt_ctrl = interrupt_ctrl;
rtc_timer_set_mode(RTC_TIMER_RUNNING);
return 0;
}
int rtc_tick_interrupt_get(void)
{
rtc_interrupt_ctrl_t interrupt_ctrl = rtc->interrupt_ctrl;
return interrupt_ctrl.tick_enable;
}
int rtc_tick_interrupt_mode_set(rtc_tick_interrupt_mode_t mode)
{
rtc_interrupt_ctrl_t interrupt_ctrl = rtc->interrupt_ctrl;
interrupt_ctrl.tick_int_mode = mode;
rtc_timer_set_mode(RTC_TIMER_SETTING);
rtc->interrupt_ctrl = interrupt_ctrl;
rtc_timer_set_mode(RTC_TIMER_RUNNING);
return 0;
}
rtc_tick_interrupt_mode_t rtc_tick_interrupt_mode_get(void)
{
rtc_interrupt_ctrl_t interrupt_ctrl = rtc->interrupt_ctrl;
return interrupt_ctrl.tick_int_mode;
}
int rtc_alarm_interrupt_set(int enable)
{
rtc_interrupt_ctrl_t interrupt_ctrl = rtc->interrupt_ctrl;
interrupt_ctrl.alarm_enable = enable;
rtc->interrupt_ctrl = interrupt_ctrl;
return 0;
}
int rtc_alarm_interrupt_get(void)
{
rtc_interrupt_ctrl_t interrupt_ctrl = rtc->interrupt_ctrl;
return interrupt_ctrl.alarm_enable;
}
int rtc_alarm_interrupt_mask_set(rtc_mask_t mask)
{
rtc_interrupt_ctrl_t interrupt_ctrl = rtc->interrupt_ctrl;
interrupt_ctrl.alarm_compare_mask = *(uint8_t *)&mask;
rtc->interrupt_ctrl = interrupt_ctrl;
return 0;
}
rtc_mask_t rtc_alarm_interrupt_mask_get(void)
{
rtc_interrupt_ctrl_t interrupt_ctrl = rtc->interrupt_ctrl;
uint8_t compare_mask = interrupt_ctrl.alarm_compare_mask;
return *(rtc_mask_t *)&compare_mask;
}
int rtc_protect_set(int enable)
{
rtc_register_ctrl_t register_ctrl = rtc->register_ctrl;
rtc_mask_t mask =
{
.second = 1,
/* Second mask */
.minute = 1,
/* Minute mask */
.hour = 1,
/* Hour mask */
.week = 1,
/* Week mask */
.day = 1,
/* Day mask */
.month = 1,
/* Month mask */
.year = 1,
};
rtc_mask_t unmask =
{
.second = 0,
/* Second mask */
.minute = 0,
/* Minute mask */
.hour = 0,
/* Hour mask */
.week = 0,
/* Week mask */
.day = 0,
/* Day mask */
.month = 0,
/* Month mask */
.year = 0,
};
if (enable)
{
/* Turn RTC in protect mode, no one can write time */
register_ctrl.TimerMask = *(uint8_t *)&unmask;
register_ctrl.alarm_mask = *(uint8_t *)&unmask;
register_ctrl.initial_count_mask = 0;
register_ctrl.interrupt_register_mask = 0;
}
else
{
/* Turn RTC in unprotect mode, everyone can write time */
register_ctrl.TimerMask = *(uint8_t *)&mask;
register_ctrl.alarm_mask = *(uint8_t *)&mask;
register_ctrl.initial_count_mask = 1;
register_ctrl.interrupt_register_mask = 1;
}
rtc_timer_set_mode(RTC_TIMER_SETTING);
rtc->register_ctrl = register_ctrl;
rtc_timer_set_mode(RTC_TIMER_RUNNING);
return 0;
}
int rtc_init(void)
{
/* Reset RTC */
sysctl_reset(SYSCTL_RESET_RTC);
/* Enable RTC */
sysctl_clock_enable(SYSCTL_CLOCK_RTC);
/* Unprotect RTC */
rtc_protect_set(0);
/* Set RTC clock frequency */
rtc_timer_set_clock_frequency(
SysctlClockGetFreq(SYSCTL_CLOCK_IN0)
);
rtc_timer_set_clock_count_value(1);
/* Set RTC mode to timer running mode */
rtc_timer_set_mode(RTC_TIMER_RUNNING);
return 0;
}

View File

@ -0,0 +1,49 @@
/* Copyright 2018 Canaan Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* @file sleep.c
* @brief add from Canaan k210 SDK
* https://canaan-creative.com/developer
* @version 1.0
* @author AIIT XUOS Lab
* @date 2021-04-25
*/
#include "sleep.h"
#include "sysctl.h"
int usleep(uint64_t usec)
{
uint64_t cycle = read_cycle();
uint64_t nop_all = usec * SysctlClockGetFreq(SYSCTL_CLOCK_CPU) / 1000000UL;
while (1)
{
if(read_cycle() - cycle >= nop_all)
break;
}
return 0;
}
int msleep(uint64_t msec)
{
return (unsigned int)usleep(msec * 1000);
}
unsigned int sleep(unsigned int seconds)
{
return (unsigned int)msleep(seconds * 1000);
}

View File

@ -0,0 +1,67 @@
config BSP_USING_SPI1
bool "Using spi1 "
default y
if BSP_USING_SPI1
config SPI_BUS_NAME_1
string "spi bus 1 name"
default "spi1"
config SPI_1_DRV_NAME
string "spi bus 1 driver name"
default "spi1_drv"
config BSP_SPI1_CLK_PIN
int "spi1 clk pin number"
default 29
config BSP_SPI1_D0_PIN
int "spi1 d0 pin number"
default 30
config BSP_SPI1_D1_PIN
int "spi1 d1 pin number"
default 31
menuconfig BSP_SPI1_USING_SS0
bool "SPI1 Enable SS0"
default y
if BSP_SPI1_USING_SS0
config SPI_1_DEVICE_NAME_0
string "spi bus 1 device 0 name"
default "spi1_dev0"
config BSP_SPI1_SS0_PIN
int "spi1 ss0 pin number"
default 32
endif
menuconfig BSP_SPI1_USING_SS1
bool "SPI1 Enable SS1"
default y
if BSP_SPI1_USING_SS1
config SPI_1_DEVICE_NAME_1
string "spi bus 1 device 1 name"
default "spi1_dev1"
config BSP_SPI1_SS1_PIN
int "spi1 ss1 pin number"
default 33
endif
menuconfig BSP_SPI1_USING_SS2
bool "SPI1 Enable SS2"
default n
if BSP_SPI1_USING_SS2
config SPI_1_DEVICE_NAME_2
string "spi bus 1 device 2 name"
default "spi1_dev2"
config BSP_SPI1_SS2_PIN
int "spi1 ss2 pin number"
default 26
endif
menuconfig BSP_SPI1_USING_SS3
bool "SPI1 Enable SS3"
default n
if BSP_SPI1_USING_SS3
config SPI_1_DEVICE_NAME_3
string "spi bus 1 device 3 name"
default "spi1_dev3"
config BSP_SPI1_SS3_PIN
int "spi1 ss3 pin number"
default 27
endif
endif

View File

@ -0,0 +1,6 @@
SRC_FILES := connect_spi.c hardware_spi.c
include $(KERNEL_ROOT)/compiler.mk

View File

@ -0,0 +1,472 @@
/*
* Copyright (c) 2020 AIIT XUOS Lab
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2019-03-18 ZYH first version
*/
/**
* @file connect_spi.c
* @brief support kd233-board spi function and register to bus framework
* @version 1.0
* @author AIIT XUOS Lab
* @date 2021-04-25
*/
/*************************************************
File name: connect_spi.c
Description: support kd233-board spi configure and spi bus register function
Others: take RT-Thread v4.0.2/bsp/k210/driver/drv_spi.c for references
https://github.com/RT-Thread/rt-thread/tree/v4.0.2
History:
1. Date: 2021-04-25
Author: AIIT XUOS Lab
Modification:
1. support kd233-board spi configure, write and read
2. support kd233-board spi bus device and driver register
*************************************************/
#include <dmac.h>
#include <sysctl.h>
#include <gpiohs.h>
#include <string.h>
#include "connect_spi.h"
#include "hardware_spi.h"
#include <drv_io_config.h>
#include "utils.h"
#ifdef BSP_SPI1_USING_SS0
#define SPI_DEVICE_SLAVE_ID_0 0
#endif
#ifdef BSP_SPI1_USING_SS1
#define SPI_DEVICE_SLAVE_ID_1 1
#endif
#ifdef BSP_SPI1_USING_SS2
#define SPI_DEVICE_SLAVE_ID_2 2
#endif
#ifdef BSP_SPI1_USING_SS3
#define SPI_DEVICE_SLAVE_ID_3 3
#endif
static volatile spi_t *const spi_instance[4] =
{
(volatile spi_t *)SPI0_BASE_ADDR,
(volatile spi_t *)SPI1_BASE_ADDR,
(volatile spi_t *)SPI_SLAVE_BASE_ADDR,
(volatile spi_t *)SPI3_BASE_ADDR
};
void __spi_set_tmod(uint8_t spi_num, uint32_t tmod)
{
CHECK(spi_num < SPI_DEVICE_MAX);
volatile spi_t *spi_handle = spi[spi_num];
uint8_t tmod_offset = 0;
switch (spi_num)
{
case 0:
case 1:
case 2:
tmod_offset = 8;
break;
case 3:
default:
tmod_offset = 10;
break;
}
set_bit(&spi_handle->ctrlr0, 3 << tmod_offset, tmod << tmod_offset);
}
/*Init the spi sdk intetface */
static uint32 SpiSdkInit(struct SpiDriver *spi_drv)
{
NULL_PARAM_CHECK(spi_drv);
uint8 cs_gpio_pin, cs_select_id;
uint32 max_frequency;
SpiDeviceParam *dev_param = (SpiDeviceParam *)(spi_drv->driver.private_data);
cs_gpio_pin = dev_param->spi_slave_param->spi_cs_gpio_pin;
cs_select_id = dev_param->spi_slave_param->spi_cs_select_id;
gpiohs_set_drive_mode(cs_select_id, GPIO_DM_OUTPUT);//Set the cs pin as output
gpiohs_set_pin(cs_gpio_pin, GPIO_PV_HIGH);//set the cs gpio high
spi_init(dev_param->spi_dma_param->spi_master_id,
dev_param->spi_master_param->spi_work_mode & SPI_MODE_3,
dev_param->spi_master_param->spi_frame_format,
dev_param->spi_master_param->spi_data_bit_width,
dev_param->spi_master_param->spi_data_endian);
max_frequency = (dev_param->spi_master_param->spi_maxfrequency < SPI_MAX_CLOCK) ? dev_param->spi_master_param->spi_maxfrequency : SPI_MAX_CLOCK;
uint32 real_freq = spi_set_clk_rate(dev_param->spi_dma_param->spi_master_id, max_frequency);
return EOK;
}
static uint32 SpiSdkCfg(struct SpiDriver *spi_drv, struct SpiMasterParam *spi_param)
{
NULL_PARAM_CHECK(spi_drv);
NULL_PARAM_CHECK(spi_param);
SpiDeviceParam *dev_param = (SpiDeviceParam *)(spi_drv->driver.private_data);
dev_param->spi_master_param = spi_param;
dev_param->spi_master_param->spi_work_mode = dev_param->spi_master_param->spi_work_mode & SPI_MODE_MASK;
dev_param->spi_master_param->spi_frame_format = SPI_FF_STANDARD;
return EOK;
}
/*Configure the spi device param, make sure struct (configure_info->private_data) = (SpiMasterParam)*/
static uint32 SpiDrvConfigure(void *drv, struct BusConfigureInfo *configure_info)
{
NULL_PARAM_CHECK(drv);
NULL_PARAM_CHECK(configure_info);
x_err_t ret = EOK;
struct SpiDriver *spi_drv = (struct SpiDriver *)drv;
struct SpiMasterParam *spi_param;
switch (configure_info->configure_cmd)
{
case OPE_INT:
ret = SpiSdkInit(spi_drv);
break;
case OPE_CFG:
spi_param = (struct SpiMasterParam *)configure_info->private_data;
ret = SpiSdkCfg(spi_drv, spi_param);
break;
default:
break;
}
return ret;
}
static uint32 SpiWriteData(struct SpiHardwareDevice *spi_dev, struct SpiDataStandard *spi_datacfg)
{
SpiDeviceParam *dev_param = (SpiDeviceParam *)(spi_dev->haldev.private_data);
uint8 device_id = dev_param->spi_slave_param->spi_slave_id;
uint8 device_master_id = dev_param->spi_dma_param->spi_master_id;
uint8 cs_gpio_pin = dev_param->spi_slave_param->spi_cs_gpio_pin;
while (NONE != spi_datacfg) {
uint32_t * tx_buff = NONE;
int i;
x_ubase dummy = 0xFFFFFFFFU;
__spi_set_tmod(device_master_id, SPI_TMOD_TRANS_RECV);
if (spi_datacfg->spi_chip_select) {
gpiohs_set_pin(cs_gpio_pin, GPIO_PV_LOW);
}
if (spi_datacfg->length) {
spi_instance[device_master_id]->dmacr = 0x3;
spi_instance[device_master_id]->ssienr = 0x01;
sysctl_dma_select(dev_param->spi_dma_param->spi_dmac_txchannel, SYSCTL_DMA_SELECT_SSI0_TX_REQ + device_master_id * 2);
sysctl_dma_select(dev_param->spi_dma_param->spi_dmac_rxchannel, SYSCTL_DMA_SELECT_SSI0_RX_REQ + device_master_id* 2);
dmac_set_single_mode(dev_param->spi_dma_param->spi_dmac_rxchannel, (void *)(&spi_instance[device_master_id]->dr[0]), &dummy, DMAC_ADDR_NOCHANGE, DMAC_ADDR_NOCHANGE,
DMAC_MSIZE_1, DMAC_TRANS_WIDTH_32, spi_datacfg->length);
if (!spi_datacfg->tx_buff) {
dmac_set_single_mode(dev_param->spi_dma_param->spi_dmac_txchannel, &dummy, (void *)(&spi_instance[device_master_id]->dr[0]), DMAC_ADDR_NOCHANGE, DMAC_ADDR_NOCHANGE,
DMAC_MSIZE_4, DMAC_TRANS_WIDTH_32, spi_datacfg->length);
} else {
tx_buff = x_malloc(spi_datacfg->length * 4);
if (!tx_buff) {
goto transfer_done;
}
for (i = 0; i < spi_datacfg->length; i++) {
tx_buff[i] = ((uint8_t *)spi_datacfg->tx_buff)[i];
}
dmac_set_single_mode(dev_param->spi_dma_param->spi_dmac_txchannel, tx_buff, (void *)(&spi_instance[device_master_id]->dr[0]), DMAC_ADDR_INCREMENT, DMAC_ADDR_NOCHANGE,
DMAC_MSIZE_4, DMAC_TRANS_WIDTH_32, spi_datacfg->length);
}
spi_instance[device_master_id]->ser = 1U << dev_param->spi_slave_param->spi_cs_select_id;
dmac_wait_done(dev_param->spi_dma_param->spi_dmac_txchannel);
dmac_wait_done(dev_param->spi_dma_param->spi_dmac_rxchannel);
spi_instance[device_master_id]->ser = 0x00;
spi_instance[device_master_id]->ssienr = 0x00;
transfer_done:
if (tx_buff) {
x_free(tx_buff);
}
}
if (spi_datacfg->spi_cs_release) {
gpiohs_set_pin(cs_gpio_pin, GPIO_PV_HIGH);
}
spi_datacfg = spi_datacfg->next;
}
return spi_datacfg->length;
}
static uint32 SpiReadData(struct SpiHardwareDevice *spi_dev, struct SpiDataStandard *spi_datacfg)
{
SpiDeviceParam *dev_param = (SpiDeviceParam *)(spi_dev->haldev.private_data);
uint8 device_id = dev_param->spi_slave_param->spi_slave_id;
uint8 device_master_id = dev_param->spi_dma_param->spi_master_id;
uint8 cs_gpio_pin = dev_param->spi_slave_param->spi_cs_gpio_pin;
while (NONE != spi_datacfg) {
uint32_t * rx_buff = NONE;
int i;
x_ubase dummy = 0xFFFFFFFFU;
__spi_set_tmod(device_master_id, SPI_TMOD_TRANS_RECV);
if (spi_datacfg->spi_chip_select) {
gpiohs_set_pin(cs_gpio_pin, GPIO_PV_LOW);
}
if (spi_datacfg->length) {
spi_instance[device_master_id]->dmacr = 0x3;
spi_instance[device_master_id]->ssienr = 0x01;
sysctl_dma_select(dev_param->spi_dma_param->spi_dmac_txchannel, SYSCTL_DMA_SELECT_SSI0_TX_REQ + device_master_id * 2);
sysctl_dma_select(dev_param->spi_dma_param->spi_dmac_rxchannel, SYSCTL_DMA_SELECT_SSI0_RX_REQ + device_master_id* 2);
dmac_set_single_mode(dev_param->spi_dma_param->spi_dmac_txchannel, &dummy, (void *)(&spi_instance[device_master_id]->dr[0]), DMAC_ADDR_NOCHANGE, DMAC_ADDR_NOCHANGE,
DMAC_MSIZE_4, DMAC_TRANS_WIDTH_32, spi_datacfg->length);
if (!spi_datacfg->rx_buff) {
dmac_set_single_mode(dev_param->spi_dma_param->spi_dmac_rxchannel, (void *)(&spi_instance[device_master_id]->dr[0]), &dummy, DMAC_ADDR_NOCHANGE, DMAC_ADDR_NOCHANGE,
DMAC_MSIZE_1, DMAC_TRANS_WIDTH_32, spi_datacfg->length);
} else {
rx_buff = x_calloc(spi_datacfg->length * 4, 1);
if (!rx_buff) {
goto transfer_done;
}
dmac_set_single_mode(dev_param->spi_dma_param->spi_dmac_rxchannel, (void *)(&spi_instance[device_master_id]->dr[0]), rx_buff, DMAC_ADDR_NOCHANGE, DMAC_ADDR_INCREMENT,
DMAC_MSIZE_1, DMAC_TRANS_WIDTH_32, spi_datacfg->length);
}
spi_instance[device_master_id]->ser = 1U << dev_param->spi_slave_param->spi_cs_select_id;
dmac_wait_done(dev_param->spi_dma_param->spi_dmac_txchannel);
dmac_wait_done(dev_param->spi_dma_param->spi_dmac_rxchannel);
spi_instance[device_master_id]->ser = 0x00;
spi_instance[device_master_id]->ssienr = 0x00;
if (spi_datacfg->rx_buff) {
for (i = 0; i < spi_datacfg->length; i++) {
((uint8_t *)spi_datacfg->rx_buff)[i] = (uint8_t)rx_buff[i];
}
}
transfer_done:
if (rx_buff) {
x_free(rx_buff);
}
}
if (spi_datacfg->spi_cs_release) {
gpiohs_set_pin(cs_gpio_pin, GPIO_PV_HIGH);
}
spi_datacfg = spi_datacfg->next;
}
return spi_datacfg->length;
}
/*manage the spi device operations*/
static const struct SpiDevDone spi_dev_done =
{
.open = NONE,
.close = NONE,
.write = SpiWriteData,
.read = SpiReadData,
};
static int BoardSpiBusInit(struct SpiBus *spi_bus, struct SpiDriver *spi_driver)
{
x_err_t ret = EOK;
/*Init the spi bus */
ret = SpiBusInit(spi_bus, SPI_BUS_NAME_1);
if (EOK != ret) {
KPrintf("Board_Spi_init SpiBusInit error %d\n", ret);
return ERROR;
}
/*Init the spi driver*/
ret = SpiDriverInit(spi_driver, SPI_1_DRV_NAME);
if (EOK != ret) {
KPrintf("Board_Spi_init SpiDriverInit error %d\n", ret);
return ERROR;
}
/*Attach the spi driver to the spi bus*/
ret = SpiDriverAttachToBus(SPI_1_DRV_NAME, SPI_BUS_NAME_1);
if (EOK != ret) {
KPrintf("Board_Spi_init SpiDriverAttachToBus error %d\n", ret);
return ERROR;
}
return ret;
}
/*Attach the spi device to the spi bus*/
static int BoardSpiDevBend(struct SpiDmaParam *spi_initparam)
{
x_err_t ret = EOK;
#ifdef BSP_SPI1_USING_SS0
static struct SpiHardwareDevice spi_device0;
memset(&spi_device0, 0, sizeof(struct SpiHardwareDevice));
static struct SpiSlaveParam spi_slaveparam0;
memset(&spi_slaveparam0, 0, sizeof(struct SpiSlaveParam));
spi_slaveparam0.spi_slave_id = SPI_DEVICE_SLAVE_ID_0;
spi_slaveparam0.spi_cs_gpio_pin = SPI1_CS0_PIN;
spi_slaveparam0.spi_cs_select_id = SPI_CHIP_SELECT_0;
spi_device0.spi_param.spi_dma_param = spi_initparam;
spi_device0.spi_param.spi_slave_param = &spi_slaveparam0;
spi_device0.spi_dev_done = &(spi_dev_done);
ret = SpiDeviceRegister(&spi_device0, (void *)(&spi_device0.spi_param), SPI_1_DEVICE_NAME_0);
if (EOK != ret) {
KPrintf("Board_Spi_init SpiDeviceInit device %s error %d\n", SPI_1_DEVICE_NAME_0, ret);
return ERROR;
}
ret = SpiDeviceAttachToBus(SPI_1_DEVICE_NAME_0, SPI_BUS_NAME_1);
if (EOK != ret) {
KPrintf("Board_Spi_init SpiDeviceAttachToBus device %s error %d\n", SPI_1_DEVICE_NAME_0, ret);
return ERROR;
}
#endif
#ifdef BSP_SPI1_USING_SS1
static struct SpiHardwareDevice spi_device1;
memset(&spi_device1, 0, sizeof(struct SpiHardwareDevice));
static struct SpiSlaveParam spi_slaveparam1;
memset(&spi_slaveparam1, 0, sizeof(struct SpiSlaveParam));
spi_slaveparam1.spi_slave_id = SPI_DEVICE_SLAVE_ID_1;
spi_slaveparam1.spi_cs_gpio_pin = SPI1_CS1_PIN;
spi_slaveparam1.spi_cs_select_id = SPI_CHIP_SELECT_1;
spi_device1.spi_param.spi_dma_param = spi_initparam;
spi_device1.spi_param.spi_slave_param = &spi_slaveparam1;
spi_device1.spi_dev_done = &(spi_dev_done);
ret = SpiDeviceRegister(&spi_device1, (void *)(&spi_device1.spi_param), SPI_1_DEVICE_NAME_1);
if (EOK != ret) {
KPrintf("Board_Spi_init SpiDeviceInit device %s error %d\n", SPI_1_DEVICE_NAME_1, ret);
return ERROR;
}
ret = SpiDeviceAttachToBus(SPI_1_DEVICE_NAME_1, SPI_BUS_NAME_1);
if (EOK != ret) {
KPrintf("Board_Spi_init SpiDeviceAttachToBus device %s error %d\n", SPI_1_DEVICE_NAME_1, ret);
return ERROR;
}
#endif
#ifdef BSP_SPI1_USING_SS2
static struct SpiHardwareDevice spi_device2;
memset(&spi_device2, 0, sizeof(struct SpiHardwareDevice));
spi_initparam->spi_slave_id[SPI_DEVICE_SLAVE_ID_2] = SPI_DEVICE_SLAVE_ID_2;
spi_initparam->spi_cs_gpio_pin[SPI_DEVICE_SLAVE_ID_2] = SPI1_CS2_PIN;
spi_initparam->spi_cs_select_id[SPI_DEVICE_SLAVE_ID_2] = SPI_CHIP_SELECT_2;
spi_device2.spi_dev_done = &(spi_dev_done);
ret = SpiDeviceRegister(&spi_device2, (void *)(&spi_device2.spi_param), SPI_1_DEVICE_NAME_2);
if (EOK != ret) {
KPrintf("Board_Spi_init SpiDeviceInit device %s error %d\n", SPI_1_DEVICE_NAME_2, ret);
return ERROR;
}
ret = SpiDeviceAttachToBus(SPI_1_DEVICE_NAME_2, SPI_BUS_NAME_1);
if (EOK != ret) {
KPrintf("Board_Spi_init SpiDeviceAttachToBus device %s error %d\n", SPI_1_DEVICE_NAME_2, ret);
return ERROR;
}
#endif
#ifdef BSP_SPI1_USING_SS3
static struct SpiHardwareDevice spi_device3;
memset(&spi_device3, 0, sizeof(struct SpiHardwareDevice));
spi_initparam->spi_slave_id[SPI_DEVICE_SLAVE_ID_3] = SPI_DEVICE_SLAVE_ID_3;
spi_initparam->spi_cs_gpio_pin[SPI_DEVICE_SLAVE_ID_3] = SPI1_CS3_PIN;
spi_initparam->spi_cs_select_id[SPI_DEVICE_SLAVE_ID_3] = SPI_CHIP_SELECT_3;
spi_device3.spi_dev_done = &(spi_dev_done);
ret = SpiDeviceRegister(&spi_device3, (void *)(&spi_device3.spi_param), SPI_1_DEVICE_NAME_3);
if (EOK != ret) {
KPrintf("Board_Spi_init SpiDeviceInit device %s error %d\n", SPI_1_DEVICE_NAME_3, ret);
return ERROR;
}
ret = SpiDeviceAttachToBus(SPI_1_DEVICE_NAME_3, SPI_BUS_NAME_1);
if (EOK != ret) {
KPrintf("Board_Spi_init SpiDeviceAttachToBus device %s error %d\n", SPI_1_DEVICE_NAME_3, ret);
return ERROR;
}
#endif
return ret;
}
/*RISC-V 64 BOARD SPI INIT*/
int HwSpiInit(void)
{
x_err_t ret = EOK;
static struct SpiDmaParam spi_initparam;
memset(&spi_initparam, 0, sizeof(struct SpiDmaParam));
#ifdef BSP_USING_SPI1
static struct SpiBus spi_bus;
memset(&spi_bus, 0, sizeof(struct SpiBus));
static struct SpiDriver spi_driver;
memset(&spi_driver, 0, sizeof(struct SpiDriver));
spi_initparam.spi_master_id = SPI_DEVICE_1;
spi_initparam.spi_dmac_txchannel = DMAC_CHANNEL1;
spi_initparam.spi_dmac_rxchannel = DMAC_CHANNEL2;
spi_driver.configure = &(SpiDrvConfigure);
ret = BoardSpiBusInit(&spi_bus, &spi_driver);
if (EOK != ret) {
KPrintf("Board_Spi_Init error ret %u\n", ret);
return ERROR;
}
ret = BoardSpiDevBend(&spi_initparam);
if (EOK != ret) {
KPrintf("Board_Spi_Init error ret %u\n", ret);
return ERROR;
}
#endif
return ret;
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1 @@

View File

@ -0,0 +1,6 @@
SRC_FILES := sysctl.c
include $(KERNEL_ROOT)/compiler.mk

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,19 @@
if BSP_USING_HWTIMER
config HWTIMER_BUS_NAME_1
string "hwtimer bus name"
default "hwtim1"
menuconfig ENABLE_TIM1
bool "enable TIM1"
default y
if ENABLE_TIM1
config HWTIMER_1_DEVICE_NAME_1
string "TIM1 dev name"
default "hwtim1_dev1"
config HWTIMER_DRIVER_NAME_1
string "TIM1 drv name"
default "hwtim1_drv"
endif
endif

View File

@ -0,0 +1,3 @@
SRC_FILES := hardware_hwtimer.c connect_hwtimer.c
include $(KERNEL_ROOT)/compiler.mk

View File

@ -0,0 +1,155 @@
/*
* Copyright (c) 2020 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
/**
* @file connect_hwtimer.c
* @brief support kd233-board hwtimer function and register to bus framework
* @version 1.0
* @author AIIT XUOS Lab
* @date 2021-04-25
*/
#include <board.h>
#include <xiuos.h>
#include <stdio.h>
#include <syslog.h>
#include <plic.h>
#include <sysctl.h>
#include <fpioa.h>
#include "connect_hwtimer.h"
static struct HwtimerCallBackInfo *ptim2_cb_info = NULL;
int timer_callback(void *ctx)
{
if (ptim2_cb_info) {
if (ptim2_cb_info->timeout_callback) {
ptim2_cb_info->timeout_callback(ptim2_cb_info->param);
}
}
return 0;
}
uint32 HwtimerOpen(void *dev)
{
struct HwtimerHardwareDevice *hwtimer_dev = dev;
ptim2_cb_info = &hwtimer_dev->hwtimer_param.cb_info;
plic_init();
sysctl_enable_irq();
timer_init(TIMER_DEVICE_1);
size_t real_time = timer_set_interval(TIMER_DEVICE_1, TIMER_CHANNEL_1, hwtimer_dev->hwtimer_param.period_millisecond *1000);
KPrintf("timer_set_interval -- real_time : %ld\n", real_time);
timer_irq_register(TIMER_DEVICE_1, TIMER_CHANNEL_1, !hwtimer_dev->hwtimer_param.repeat, 1, timer_callback, NULL);
timer_set_enable(TIMER_DEVICE_1, TIMER_CHANNEL_1, 1);
return EOK;
}
uint32 HwtimerClose(void *dev)
{
timer_set_enable(TIMER_DEVICE_1, TIMER_CHANNEL_1, 0);
return EOK;
}
/*manage the hwtimer device operations*/
static const struct HwtimerDevDone dev_done =
{
.open = HwtimerOpen,
.close = HwtimerClose,
.write = NONE,
.read = NONE,
};
/*Init hwtimer bus*/
static int BoardHwtimerBusInit(struct HwtimerBus *hwtimer_bus, struct HwtimerDriver *hwtimer_driver)
{
x_err_t ret = EOK;
/*Init the hwtimer bus */
ret = HwtimerBusInit(hwtimer_bus, HWTIMER_BUS_NAME_1);
if (EOK != ret) {
KPrintf("board_hwtimer_init HwtimerBusInit error %d\n", ret);
return ERROR;
}
/*Init the hwtimer driver*/
hwtimer_driver->configure = NONE;
ret = HwtimerDriverInit(hwtimer_driver, HWTIMER_DRIVER_NAME_1);
if (EOK != ret) {
KPrintf("board_hwtimer_init HwtimerDriverInit error %d\n", ret);
return ERROR;
}
/*Attach the hwtimer driver to the hwtimer bus*/
ret = HwtimerDriverAttachToBus(HWTIMER_DRIVER_NAME_1, HWTIMER_BUS_NAME_1);
if (EOK != ret) {
KPrintf("board_hwtimer_init USEDriverAttachToBus error %d\n", ret);
return ERROR;
}
return ret;
}
/*Attach the hwtimer device to the hwtimer bus*/
static int BoardHwtimerDevBend(void)
{
x_err_t ret = EOK;
static struct HwtimerHardwareDevice hwtimer_device_0;
memset(&hwtimer_device_0, 0, sizeof(struct HwtimerHardwareDevice));
hwtimer_device_0.dev_done = &dev_done;
ret = HwtimerDeviceRegister(&hwtimer_device_0, NONE, HWTIMER_1_DEVICE_NAME_1);
if (EOK != ret) {
KPrintf("board_hwtimer_init HWTIMERDeviceInit device %s error %d\n", HWTIMER_1_DEVICE_NAME_1, ret);
return ERROR;
}
ret = HwtimerDeviceAttachToBus(HWTIMER_1_DEVICE_NAME_1, HWTIMER_BUS_NAME_1);
if (EOK != ret) {
KPrintf("board_hwtimer_init HwtimerDeviceAttachToBus device %s error %d\n", HWTIMER_1_DEVICE_NAME_1, ret);
return ERROR;
}
return ret;
}
/*K210 BOARD HWTIMER INIT*/
int HwTimerInit(void)
{
x_err_t ret = EOK;
static struct HwtimerBus hwtimer_bus;
memset(&hwtimer_bus, 0, sizeof(struct HwtimerBus));
static struct HwtimerDriver hwtimer_driver;
memset(&hwtimer_driver, 0, sizeof(struct HwtimerDriver));
ret = BoardHwtimerBusInit(&hwtimer_bus, &hwtimer_driver);
if (EOK != ret) {
KPrintf("board_hwtimer_Init error ret %u\n", ret);
return ERROR;
}
ret = BoardHwtimerDevBend();
if (EOK != ret) {
KPrintf("board_hwtimer_Init error ret %u\n", ret);
return ERROR;
}
return ret;
}

View File

@ -0,0 +1,406 @@
/* Copyright 2018 Canaan Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* @file hardware_hwtimer.c
* @brief add from Canaan k210 SDK
* https://canaan-creative.com/developer
* @version 1.0
* @author AIIT XUOS Lab
* @date 2021-04-25
*/
#include <syslog.h>
#include "hardware_hwtimer.h"
#include "sysctl.h"
#include "stddef.h"
#include "utils.h"
#include "plic.h"
#include "io.h"
#include "xs_isr.h"
/**
* @brief Private definitions for the timer instance
*/
typedef struct timer_instance
{
timer_callback_t callback;
void *ctx;
bool single_shot;
} timer_instance_t;
typedef void(*irq_manager_callback_t)(int irq, void* arg);
volatile timer_instance_t timer_instance[TIMER_DEVICE_MAX][TIMER_CHANNEL_MAX];
volatile kendryte_timer_t *const timer[3] =
{
(volatile kendryte_timer_t *)TIMER0_BASE_ADDR,
(volatile kendryte_timer_t *)TIMER1_BASE_ADDR,
(volatile kendryte_timer_t *)TIMER2_BASE_ADDR
};
void timer_init(timer_device_number_t timer_number)
{
for(size_t i = 0; i < TIMER_CHANNEL_MAX; i++)
timer_instance[timer_number][i] = (const timer_instance_t) {
.callback = NULL,
.ctx = NULL,
.single_shot = 0,
};
sysctl_clock_enable(SYSCTL_CLOCK_TIMER0 + timer_number);
}
void timer_set_clock_div(timer_device_number_t timer_number, uint32_t div)
{
sysctl_clock_set_threshold(timer_number == 0 ? SYSCTL_THRESHOLD_TIMER0 :
timer_number == 1 ? SYSCTL_THRESHOLD_TIMER1 :
SYSCTL_THRESHOLD_TIMER2, div);
}
void timer_enable(timer_device_number_t timer_number, timer_channel_number_t channel)
{
timer[timer_number]->channel[channel].control |= TIMER_CR_ENABLE;
}
void timer_disable(timer_device_number_t timer_number, timer_channel_number_t channel)
{
timer[timer_number]->channel[channel].control &= (~TIMER_CR_ENABLE);
}
void timer_enable_pwm(timer_device_number_t timer_number, timer_channel_number_t channel)
{
timer[timer_number]->channel[channel].control |= TIMER_CR_PWM_ENABLE;
}
void timer_disable_pwm(timer_device_number_t timer_number, timer_channel_number_t channel)
{
timer[timer_number]->channel[channel].control &= (~TIMER_CR_PWM_ENABLE);
}
void timer_enable_interrupt(timer_device_number_t timer_number, timer_channel_number_t channel)
{
timer[timer_number]->channel[channel].control &= (~TIMER_CR_INTERRUPT_MASK);
}
void timer_disable_interrupt(timer_device_number_t timer_number, timer_channel_number_t channel)
{
timer[timer_number]->channel[channel].control |= TIMER_CR_INTERRUPT_MASK;
}
void timer_set_mode(timer_device_number_t timer_number, timer_channel_number_t channel, uint32_t mode)
{
timer[timer_number]->channel[channel].control &= (~TIMER_CR_MODE_MASK);
timer[timer_number]->channel[channel].control |= mode;
}
void timer_set_reload(timer_device_number_t timer_number, timer_channel_number_t channel, uint32_t count)
{
timer[timer_number]->channel[channel].load_count = count;
}
void timer_set_reload2(timer_device_number_t timer_number, timer_channel_number_t channel, uint32_t count)
{
timer[timer_number]->load_count2[channel] = count;
}
uint32_t timer_get_count(timer_device_number_t timer_number, timer_channel_number_t channel)
{
return timer[timer_number]->channel[channel].current_value;
}
uint32_t timer_get_reload(timer_device_number_t timer_number, timer_channel_number_t channel)
{
return timer[timer_number]->channel[channel].load_count;
}
uint32_t timer_get_reload2(timer_device_number_t timer_number, timer_channel_number_t channel)
{
return timer[timer_number]->load_count2[channel];
}
uint32_t timer_get_interrupt_status(timer_device_number_t timer_number)
{
return timer[timer_number]->intr_stat;
}
uint32_t timer_get_raw_interrupt_status(timer_device_number_t timer_number)
{
return timer[timer_number]->raw_intr_stat;
}
uint32_t timer_channel_get_interrupt_status(timer_device_number_t timer_number, timer_channel_number_t channel)
{
return timer[timer_number]->channel[channel].intr_stat;
}
void timer_clear_interrupt(timer_device_number_t timer_number)
{
timer[timer_number]->eoi = timer[timer_number]->eoi;
}
void timer_channel_clear_interrupt(timer_device_number_t timer_number, timer_channel_number_t channel)
{
timer[timer_number]->channel[channel].eoi = timer[timer_number]->channel[channel].eoi;
}
void timer_set_enable(timer_device_number_t timer_number, timer_channel_number_t channel, uint32_t enable)
{
if (enable)
timer[timer_number]->channel[channel].control = TIMER_CR_USER_MODE | TIMER_CR_ENABLE;
else
timer[timer_number]->channel[channel].control = TIMER_CR_INTERRUPT_MASK;
}
size_t timer_set_interval(timer_device_number_t timer_number, timer_channel_number_t channel, size_t useconds)
{
uint32_t clk_freq = SysctlClockGetFreq(SYSCTL_CLOCK_TIMER0 + timer_number);
double min_step = 1e6 / clk_freq;
size_t value = (size_t)(useconds / min_step);
configASSERT(value > 0 && value < UINT32_MAX);
timer[timer_number]->channel[channel].load_count = (uint32_t)value;
return (size_t)(min_step * value);
}
typedef void(*timer_ontick)();
timer_ontick time_irq[3][4] = { NULL };
static int timer_isr(void *parm)
{
uint32_t timer_number;
for (timer_number = 0; timer_number < 3; timer_number++)
{
if (parm == timer[timer_number])
break;
}
uint32_t channel = timer[timer_number]->intr_stat;
size_t i = 0;
for (i = 0; i < 4; i++)
{
if (channel & 1)
{
if (time_irq[timer_number][i])
(time_irq[timer_number][i])();
break;
}
channel >>= 1;
}
readl(&timer[timer_number]->eoi);
return 0;
}
void timer_set_irq(timer_device_number_t timer_number, timer_channel_number_t channel, void(*func)(), uint32_t priority)
{
time_irq[timer_number][channel] = func;
if (channel < 2)
{
plic_set_priority(IRQN_TIMER0A_INTERRUPT + timer_number * 2, priority);
plic_irq_register(IRQN_TIMER0A_INTERRUPT + timer_number * 2, timer_isr, (void *)timer[timer_number]);
plic_irq_enable(IRQN_TIMER0A_INTERRUPT + timer_number * 2);
}
else
{
plic_set_priority(IRQN_TIMER0B_INTERRUPT + timer_number * 2, priority);
plic_irq_register(IRQN_TIMER0B_INTERRUPT + timer_number * 2, timer_isr, (void *)timer[timer_number]);
plic_irq_enable(IRQN_TIMER0B_INTERRUPT + timer_number * 2);
}
}
/**
* @brief Get the timer irqn by device and channel object
*
* @note Internal function, not public
* @param device The device
* @param channel The channel
* @return plic_irq_t IRQ number
*/
static plic_irq_t get_timer_irqn_by_device_and_channel(timer_device_number_t device, timer_channel_number_t channel)
{
if (device < TIMER_DEVICE_MAX && channel < TIMER_CHANNEL_MAX) {
/*
* Select timer interrupt part
* Hierarchy of Timer interrupt to PLIC
* +---------+ +-----------+
* | 0+----+ | |
* | | +--+0A |
* | 1+----+ | |
* | TIMER0 | | |
* | 2+----+ | |
* | | +--+0B |
* | 3+----+ | |
* +---------+ | |
* | |
* +---------+ | |
* | 0+----+ | |
* | | +--+1A |
* | 1+----+ | |
* | TIMER1 | | PLIC |
* | 2+----+ | |
* | | +--+1B |
* | 3+----+ | |
* +---------+ | |
* | |
* +---------+ | |
* | 0+----+ | |
* | | +--+2A |
* | 1+----+ | |
* | TIMER2 | | |
* | 2+----+ | |
* | | +--+2B |
* | 3+----+ | |
* +---------+ +-----------+
*
*/
if (channel < 2) {
/* It is part A interrupt, offset + 0 */
return IRQN_TIMER0A_INTERRUPT + device * 2;
}
else {
/* It is part B interrupt, offset + 1 */
return IRQN_TIMER0B_INTERRUPT + device * 2;
}
}
return IRQN_NO_INTERRUPT;
}
/**
* @brief Process user callback function
*
* @note Internal function, not public
* @param device The timer device
* @param ctx The context
* @return int The callback result
*/
static int timer_interrupt_handler(timer_device_number_t device, void *ctx)
{
uint32_t channel_int_stat = timer[device]->intr_stat;
for (size_t i = 0; i < TIMER_CHANNEL_MAX; i++)
{
/* Check every bit for interrupt status */
if (channel_int_stat & 1)
{
if (timer_instance[device][i].callback) {
/* Process user callback function */
timer_instance[device][i].callback(timer_instance[device][i].ctx);
/* Check if this timer is a single shot timer */
if (timer_instance[device][i].single_shot) {
/* Single shot timer, disable it */
timer_set_enable(device, i, 0);
}
}
/* Clear timer interrupt flag for specific channel */
readl(&timer[device]->channel[i].eoi);
}
channel_int_stat >>= 1;
}
/*
* NOTE:
* Don't read timer[device]->eoi here, or you will lost some interrupt
* readl(&timer[device]->eoi);
*/
return 0;
}
/**
* @brief Callback function bus for timer interrupt
*
* @note Internal function, not public
* @param ctx The context
* @return int The callback result
*/
static void timer0_interrupt_callback(int irq, void *ctx)
{
timer_interrupt_handler(TIMER_DEVICE_0, ctx);
}
/**
* @brief Callback function bus for timer interrupt
*
* @note Internal function, not public
* @param ctx The context
* @return int The callback result
*/
static void timer1_interrupt_callback(int irq, void *ctx)
{
timer_interrupt_handler(TIMER_DEVICE_1, ctx);
}
/**
* @brief Callback function bus for timer interrupt
*
* @note Internal function, not public
* @param ctx The context
* @return int The callback result
*/
static void timer2_interrupt_callback(int irq, void *ctx)
{
timer_interrupt_handler(TIMER_DEVICE_2, ctx);
}
int timer_irq_register(timer_device_number_t device, timer_channel_number_t channel, int is_single_shot, uint32_t priority, timer_callback_t callback, void *ctx)
{
if (device < TIMER_DEVICE_MAX && channel < TIMER_CHANNEL_MAX) {
plic_irq_t irq_number = get_timer_irqn_by_device_and_channel(device, channel);
irq_manager_callback_t plic_irq_callback[TIMER_DEVICE_MAX] = {
timer0_interrupt_callback,
timer1_interrupt_callback,
timer2_interrupt_callback,
};
timer_instance[device][channel] = (const timer_instance_t) {
.callback = callback,
.ctx = ctx,
.single_shot = is_single_shot,
};
// plic_set_priority(irq_number, priority);
// plic_irq_register(irq_number, plic_irq_callback[device], (void *)&timer_instance[device]);
// plic_irq_enable(irq_number);
isrManager.done->registerIrq(irq_number, plic_irq_callback[device], NULL);
isrManager.done->enableIrq(irq_number);
return 0;
}
return -1;
}
int timer_irq_unregister(timer_device_number_t device, timer_channel_number_t channel)
{
if (device < TIMER_DEVICE_MAX && channel < TIMER_CHANNEL_MAX) {
timer_instance[device][channel] = (const timer_instance_t) {
.callback = NULL,
.ctx = NULL,
.single_shot = 0,
};
/* Combine 0 and 1 to A interrupt, 2 and 3 to B interrupt */
if ((!(timer_instance[device][TIMER_CHANNEL_0].callback ||
timer_instance[device][TIMER_CHANNEL_1].callback)) ||
(!(timer_instance[device][TIMER_CHANNEL_2].callback ||
timer_instance[device][TIMER_CHANNEL_3].callback))) {
plic_irq_t irq_number = get_timer_irqn_by_device_and_channel(device, channel);
plic_irq_unregister(irq_number);
}
return 0;
}
return -1;
}

View File

@ -0,0 +1,77 @@
menuconfig BSP_USING_UART_HS
bool "Enable High Speed UART"
default y
if BSP_USING_UART_HS
config SERIAL_BUS_NAME_0
string "serial high speed bus 0 name"
default "uart0"
config SERIAL_DRV_NAME_0
string "serial high speed bus 0 driver name"
default "uart0_drv"
config SERIAL_0_DEVICE_NAME_0
string "serial high speed bus 0 device 0 name"
default "uart0_dev0"
endif
menuconfig BSP_USING_UART1
bool "Enable UART1"
default y
if BSP_USING_UART1
config BSP_UART1_TXD_PIN
int "uart1 TXD pin number"
default 20
config BSP_UART1_RXD_PIN
int "uart1 RXD pin number"
default 21
config SERIAL_BUS_NAME_1
string "serial bus 1 name"
default "uart1"
config SERIAL_DRV_NAME_1
string "serial bus 1 driver name"
default "uart1_drv"
config SERIAL_1_DEVICE_NAME_0
string "serial bus 1 device 0 name"
default "uart1_dev1"
endif
menuconfig BSP_USING_UART2
bool "Enable UART2"
default y
if BSP_USING_UART2
config BSP_UART2_TXD_PIN
int "uart2 TXD pin number"
default 28
config BSP_UART2_RXD_PIN
int "uart2 RXD pin number"
default 27
config SERIAL_BUS_NAME_2
string "serial bus 2 name"
default "uart2"
config SERIAL_DRV_NAME_2
string "serial bus 2 driver name"
default "uart2_drv"
config SERIAL_2_DEVICE_NAME_0
string "serial bus 2 device 0 name"
default "uart2_dev2"
endif
menuconfig BSP_USING_UART3
bool "Enable UART3"
default y
if BSP_USING_UART3
config BSP_UART3_TXD_PIN
int "uart3 TXD pin number"
default 22
config BSP_UART3_RXD_PIN
int "uart3 RXD pin number"
default 23
config SERIAL_BUS_NAME_3
string "serial bus 3 name"
default "uart3"
config SERIAL_DRV_NAME_3
string "serial bus 3 driver name"
default "uart3_drv"
config SERIAL_3_DEVICE_NAME_0
string "serial bus 3 device 0 name"
default "uart3_dev3"
endif

View File

@ -0,0 +1,3 @@
SRC_FILES := connect_uart.c
include $(KERNEL_ROOT)/compiler.mk

View File

@ -0,0 +1,653 @@
/*
* Copyright (c) 2020 RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
*/
/**
* @file connect_uart.c
* @brief support kd233-board uart function and register to bus framework
* @version 1.0
* @author AIIT XUOS Lab
* @date 2021-04-25
*/
/*************************************************
File name: connect_uart.c
Description: support kd233-board uart configure and uart bus register function
Others: take RT-Thread v4.0.2/bsp/k210/driver/drv_uart.c for references
https://github.com/RT-Thread/rt-thread/tree/v4.0.2
History:
1. Date: 2021-04-25
Author: AIIT XUOS Lab
Modification:
1. support kd233-board uart configure, write and read
2. support kd233-board uart bus device and driver register
*************************************************/
#include <sysctl.h>
#include <stdio.h>
#include "plic.h"
#include "connect_uart.h"
#include "hardware_uart.h"
#include "hardware_uarths.h"
static volatile UarthsT *const _uarths = (volatile UarthsT *)UARTHS_BASE_ADDR;
/* START ported from kendryte standalone sdk uart.c */
#define __UART_BRATE_CONST 16
volatile UartT* const _uart_new[3] =
{
(volatile UartT*)UART1_BASE_ADDR,
(volatile UartT*)UART2_BASE_ADDR,
(volatile UartT*)UART3_BASE_ADDR
};
void _uart_init_new(UartDeviceNumberT channel)
{
sysctl_clock_enable(SYSCTL_CLOCK_UART1 + channel);
sysctl_reset(SYSCTL_RESET_UART1 + channel);
}
/* END ported from kendryte standalone sdk uart.c */
static inline UartDeviceNumberT GetUartChannel(uint32 addr)
{
switch (addr)
{
case UART1_BASE_ADDR:
return UART_DEVICE_1;
case UART2_BASE_ADDR:
return UART_DEVICE_2;
case UART3_BASE_ADDR:
return UART_DEVICE_3;
default:
return UART_DEVICE_MAX;
}
}
extern void SerialSetIsr(struct SerialHardwareDevice *serial_dev, int event);
static void SerialCfgParamCheck(struct SerialCfgParam *serial_cfg_default, struct SerialCfgParam *serial_cfg_new)
{
struct SerialDataCfg *data_cfg_default = &serial_cfg_default->data_cfg;
struct SerialDataCfg *data_cfg_new = &serial_cfg_new->data_cfg;
if ((data_cfg_default->serial_baud_rate != data_cfg_new->serial_baud_rate) && (data_cfg_new->serial_baud_rate)) {
data_cfg_default->serial_baud_rate = data_cfg_new->serial_baud_rate;
}
if ((data_cfg_default->serial_bit_order != data_cfg_new->serial_bit_order) && (data_cfg_new->serial_bit_order)) {
data_cfg_default->serial_bit_order = data_cfg_new->serial_bit_order;
}
if ((data_cfg_default->serial_buffer_size != data_cfg_new->serial_buffer_size) && (data_cfg_new->serial_buffer_size)) {
data_cfg_default->serial_buffer_size = data_cfg_new->serial_buffer_size;
}
if ((data_cfg_default->serial_data_bits != data_cfg_new->serial_data_bits) && (data_cfg_new->serial_data_bits)) {
data_cfg_default->serial_data_bits = data_cfg_new->serial_data_bits;
}
if ((data_cfg_default->serial_invert_mode != data_cfg_new->serial_invert_mode) && (data_cfg_new->serial_invert_mode)) {
data_cfg_default->serial_invert_mode = data_cfg_new->serial_invert_mode;
}
if ((data_cfg_default->serial_parity_mode != data_cfg_new->serial_parity_mode) && (data_cfg_new->serial_parity_mode)) {
data_cfg_default->serial_parity_mode = data_cfg_new->serial_parity_mode;
}
if ((data_cfg_default->serial_stop_bits != data_cfg_new->serial_stop_bits) && (data_cfg_new->serial_stop_bits)) {
data_cfg_default->serial_stop_bits = data_cfg_new->serial_stop_bits;
}
}
/* UARTHS ISR */
static void UarthsIrqHandler(int irqno, void *param)
{
struct SerialBus *serial_bus = (struct SerialBus *)param;
struct SerialDriver *serial_drv = (struct SerialDriver *)serial_bus->bus.owner_driver;
struct SerialHardwareDevice *serial_dev = (struct SerialHardwareDevice *)serial_bus->bus.owner_haldev;
struct SerialCfgParam *serial_cfg = (struct SerialCfgParam *)serial_drv->private_data;
CHECK(UARTHS_BASE_ADDR == serial_cfg->hw_cfg.serial_register_base);
/* read interrupt status and clear it */
if(_uarths->ip.rxwm)
SerialSetIsr(serial_dev, SERIAL_EVENT_RX_IND);
}
/* UART ISR */
static void UartIrqHandler(int irqno, void *param)
{
struct SerialBus *serial_bus = (struct SerialBus *)param;
struct SerialDriver *serial_drv = (struct SerialDriver *)serial_bus->bus.owner_driver;
struct SerialHardwareDevice *serial_dev = (struct SerialHardwareDevice *)serial_bus->bus.owner_haldev;
struct SerialCfgParam *serial_cfg = (struct SerialCfgParam *)serial_drv->private_data;
UartDeviceNumberT channel = GetUartChannel(serial_cfg->hw_cfg.serial_register_base);
CHECK(channel != UART_DEVICE_MAX);
/* read interrupt status and clear it */
if(_uart_new[channel]->LSR)
SerialSetIsr(serial_dev, SERIAL_EVENT_RX_IND);
}
static uint32 SerialHsInit(struct SerialDriver *serial_drv, struct BusConfigureInfo *configure_info)
{
NULL_PARAM_CHECK(serial_drv);
struct SerialCfgParam *serial_cfg = (struct SerialCfgParam *)serial_drv->private_data;
if (configure_info->private_data) {
struct SerialCfgParam *serial_cfg_new = (struct SerialCfgParam *)configure_info->private_data;
SerialCfgParamCheck(serial_cfg, serial_cfg_new);
}
//uint32 freq_hs = SysctlClockGetFreq(SYSCTL_CLOCK_CPU);
uint32 freq_hs = 26000000;
uint16 div_hs = freq_hs / serial_cfg->data_cfg.serial_baud_rate - 1;
if (UARTHS_BASE_ADDR == serial_cfg->hw_cfg.serial_register_base) {
_uarths->div.div = div_hs;
_uarths->txctrl.txen = 1;
_uarths->rxctrl.rxen = 1;
_uarths->txctrl.txcnt = 0;
_uarths->rxctrl.rxcnt = 0;
_uarths->ip.txwm = 1;
_uarths->ip.rxwm = 1;
_uarths->ie.txwm = 0;
_uarths->ie.rxwm = 1;
} else {
KPrintf("SerialHsInit error base 0x%x\n", serial_cfg->hw_cfg.serial_register_base);
return ERROR;
}
return EOK;
}
static uint32 SerialHsConfigure(struct SerialDriver *serial_drv, int serial_operation_cmd)
{
NULL_PARAM_CHECK(serial_drv);
struct SerialCfgParam *serial_cfg = (struct SerialCfgParam *)serial_drv->private_data;
struct SerialBus *serial_bus = CONTAINER_OF(serial_drv->driver.owner_bus, struct SerialBus, bus);
switch (serial_operation_cmd)
{
case OPER_CLR_INT:
isrManager.done->disableIrq(serial_cfg->hw_cfg.serial_irq_interrupt);
break;
case OPER_SET_INT:
isrManager.done->registerIrq(serial_cfg->hw_cfg.serial_irq_interrupt, UarthsIrqHandler, serial_bus);
isrManager.done->enableIrq(serial_cfg->hw_cfg.serial_irq_interrupt);
break;
}
return EOK;
}
static int SerialHsPutChar(struct SerialHardwareDevice *serial_dev, char c)
{
struct SerialCfgParam *serial_cfg = (struct SerialCfgParam *)serial_dev->private_data;
CHECK(serial_cfg->hw_cfg.serial_register_base == UARTHS_BASE_ADDR);
while (_uarths->txdata.full);
_uarths->txdata.data = (uint8)c;
return EOK;
}
static int SerialHsGetChar(struct SerialHardwareDevice *serial_dev)
{
struct SerialCfgParam *serial_cfg = (struct SerialCfgParam *)serial_dev->private_data;
CHECK(serial_cfg->hw_cfg.serial_register_base == UARTHS_BASE_ADDR);
uarths_rxdata_t recv = _uarths->rxdata;
if (recv.empty)
return -ERROR;
else
return (recv.data & 0xff);
return -ERROR;
}
static uint32 SerialInit(struct SerialDriver *serial_drv, struct BusConfigureInfo *configure_info)
{
NULL_PARAM_CHECK(serial_drv);
struct SerialCfgParam *serial_cfg = (struct SerialCfgParam *)serial_drv->private_data;
if (configure_info->private_data) {
struct SerialCfgParam *serial_cfg_new = (struct SerialCfgParam *)configure_info->private_data;
SerialCfgParamCheck(serial_cfg, serial_cfg_new);
}
UartBitwidthPointer DataWidth = (UartBitwidthPointer)serial_cfg->data_cfg.serial_data_bits;
UartStopbitT stopbit = (UartStopbitT)(serial_cfg->data_cfg.serial_stop_bits - 1);
UartParityT parity = (UartParityT)(serial_cfg->data_cfg.serial_parity_mode - 1);
uint32 freq = SysctlClockGetFreq(SYSCTL_CLOCK_APB0);
uint32 divisor = freq / (uint32)serial_cfg->data_cfg.serial_baud_rate;
uint8 dlh = divisor >> 12;
uint8 dll = (divisor - (dlh << 12)) / __UART_BRATE_CONST;
uint8 dlf = divisor - (dlh << 12) - dll * __UART_BRATE_CONST;
UartDeviceNumberT channel = GetUartChannel(serial_cfg->hw_cfg.serial_register_base);
CHECK(channel != UART_DEVICE_MAX);
CHECK(DataWidth >= 5 && DataWidth <= 8);
if (DataWidth == 5) {
CHECK(stopbit != UART_STOP_2);
} else {
CHECK(stopbit != UART_STOP_1_5);
}
uint32 stopbit_val = stopbit == UART_STOP_1 ? 0 : 1;
uint32 ParityVal;
switch (parity)
{
case UART_PARITY_NONE:
ParityVal = 0;
break;
case UART_PARITY_ODD:
ParityVal = 1;
break;
case UART_PARITY_EVEN:
ParityVal = 3;
break;
default:
CHECK(!"Invalid parity");
break;
}
_uart_new[channel]->LCR |= 1u << 7;
_uart_new[channel]->DLH = dlh;
_uart_new[channel]->DLL = dll;
_uart_new[channel]->DLF = dlf;
_uart_new[channel]->LCR = 0;
_uart_new[channel]->LCR = (DataWidth - 5) |
(stopbit_val << 2) |
(ParityVal << 3);
_uart_new[channel]->LCR &= ~(1u << 7);
_uart_new[channel]->IER |= 0x80; /* THRE */
_uart_new[channel]->FCR = UART_RECEIVE_FIFO_1 << 6 |
UART_SEND_FIFO_8 << 4 |
0x1 << 3 |
0x1;
return EOK;
}
static uint32 SerialConfigure(struct SerialDriver *serial_drv, int serial_operation_cmd)
{
NULL_PARAM_CHECK(serial_drv);
struct SerialCfgParam *serial_cfg = (struct SerialCfgParam *)serial_drv->private_data;
struct SerialBus *serial_bus = CONTAINER_OF(serial_drv->driver.owner_bus, struct SerialBus, bus);
UartDeviceNumberT channel = GetUartChannel(serial_cfg->hw_cfg.serial_register_base);
CHECK(channel != UART_DEVICE_MAX);
switch (serial_operation_cmd)
{
case OPER_CLR_INT:
/* Disable the UART Interrupt */
isrManager.done->disableIrq(serial_cfg->hw_cfg.serial_irq_interrupt);
_uart_new[channel]->IER &= ~0x1;
break;
case OPER_SET_INT:
/* install interrupt */
isrManager.done->registerIrq(serial_cfg->hw_cfg.serial_irq_interrupt, UartIrqHandler, serial_bus);
isrManager.done->enableIrq(serial_cfg->hw_cfg.serial_irq_interrupt);
_uart_new[channel]->IER |= 0x1;
break;
}
return EOK;
}
static int SerialPutChar(struct SerialHardwareDevice *serial_dev, char c)
{
struct SerialCfgParam *serial_cfg = (struct SerialCfgParam *)serial_dev->private_data;
UartDeviceNumberT channel = GetUartChannel(serial_cfg->hw_cfg.serial_register_base);
CHECK(channel != UART_DEVICE_MAX);
while (_uart_new[channel]->LSR & (1u << 5));
_uart_new[channel]->THR = c;
return EOK;
}
static int SerialGetChar(struct SerialHardwareDevice *serial_dev)
{
struct SerialCfgParam *serial_cfg = (struct SerialCfgParam *)serial_dev->private_data;
UartDeviceNumberT channel = GetUartChannel(serial_cfg->hw_cfg.serial_register_base);
CHECK(channel != UART_DEVICE_MAX);
if (_uart_new[channel]->LSR & 1)
return (char)(_uart_new[channel]->RBR & 0xff);
else
return -ERROR;
return -ERROR;
}
static uint32 SerialHsDrvConfigure(void *drv, struct BusConfigureInfo *configure_info)
{
NULL_PARAM_CHECK(drv);
NULL_PARAM_CHECK(configure_info);
x_err_t ret = EOK;
int serial_operation_cmd;
struct SerialDriver *serial_drv = (struct SerialDriver *)drv;
switch (configure_info->configure_cmd)
{
case OPE_INT:
ret = SerialHsInit(serial_drv, configure_info);
break;
case OPE_CFG:
serial_operation_cmd = *((int *)configure_info->private_data);
ret = SerialHsConfigure(serial_drv, serial_operation_cmd);
break;
default:
break;
}
return ret;
}
static uint32 SerialDrvConfigure(void *drv, struct BusConfigureInfo *configure_info)
{
NULL_PARAM_CHECK(drv);
NULL_PARAM_CHECK(configure_info);
x_err_t ret = EOK;
int serial_operation_cmd;
struct SerialDriver *serial_drv = (struct SerialDriver *)drv;
switch (configure_info->configure_cmd)
{
case OPE_INT:
ret = SerialInit(serial_drv, configure_info);
break;
case OPE_CFG:
serial_operation_cmd = *(int *)configure_info->private_data;
ret = SerialConfigure(serial_drv, serial_operation_cmd);
break;
default:
break;
}
return ret;
}
static const struct SerialDataCfg data_cfg_init =
{
.serial_baud_rate = BAUD_RATE_115200,
.serial_data_bits = DATA_BITS_8,
.serial_stop_bits = STOP_BITS_1,
.serial_parity_mode = PARITY_NONE,
.serial_bit_order = BIT_ORDER_LSB,
.serial_invert_mode = NRZ_NORMAL,
.serial_buffer_size = SERIAL_RB_BUFSZ,
};
/*manage the serial high speed device operations*/
static const struct SerialDrvDone drv_done_hs =
{
.init = SerialHsInit,
.configure = SerialHsConfigure,
};
/*manage the serial high speed device hal operations*/
static struct SerialHwDevDone hwdev_done_hs =
{
.put_char = SerialHsPutChar,
.get_char = SerialHsGetChar,
};
/*manage the serial device operations*/
static const struct SerialDrvDone drv_done =
{
.init = SerialInit,
.configure = SerialConfigure,
};
/*manage the serial device hal operations*/
static struct SerialHwDevDone hwdev_done =
{
.put_char = SerialPutChar,
.get_char = SerialGetChar,
};
static int BoardSerialBusInit(struct SerialBus *serial_bus, struct SerialDriver *serial_driver, const char *bus_name, const char *drv_name)
{
x_err_t ret = EOK;
/*Init the serial bus */
ret = SerialBusInit(serial_bus, bus_name);
if (EOK != ret) {
KPrintf("hw_serial_init SerialBusInit error %d\n", ret);
return ERROR;
}
/*Init the serial driver*/
ret = SerialDriverInit(serial_driver, drv_name);
if (EOK != ret) {
KPrintf("hw_serial_init SerialDriverInit error %d\n", ret);
return ERROR;
}
/*Attach the serial driver to the serial bus*/
ret = SerialDriverAttachToBus(drv_name, bus_name);
if (EOK != ret) {
KPrintf("hw_serial_init SerialDriverAttachToBus error %d\n", ret);
return ERROR;
}
return ret;
}
/*Attach the serial device to the serial bus*/
static int BoardSerialDevBend(struct SerialHardwareDevice *serial_device, void *serial_param, const char *bus_name, const char *dev_name)
{
x_err_t ret = EOK;
ret = SerialDeviceRegister(serial_device, serial_param, dev_name);
if (EOK != ret) {
KPrintf("hw_serial_init SerialDeviceInit device %s error %d\n", dev_name, ret);
return ERROR;
}
ret = SerialDeviceAttachToBus(dev_name, bus_name);
if (EOK != ret) {
KPrintf("hw_serial_init SerialDeviceAttachToBus device %s error %d\n", dev_name, ret);
return ERROR;
}
return ret;
}
int HwUartInit(void)
{
x_err_t ret = EOK;
#ifdef BSP_USING_UART_HS
static struct SerialBus serial_bus_hs;
memset(&serial_bus_hs, 0, sizeof(struct SerialBus));
static struct SerialDriver serial_driver_hs;
memset(&serial_driver_hs, 0, sizeof(struct SerialDriver));
static struct SerialHardwareDevice serial_device_hs;
memset(&serial_device_hs, 0, sizeof(struct SerialHardwareDevice));
static struct SerialCfgParam serial_cfg_hs;
memset(&serial_cfg_hs, 0, sizeof(struct SerialCfgParam));
static struct SerialDevParam serial_dev_param_hs;
memset(&serial_dev_param_hs, 0, sizeof(struct SerialDevParam));
serial_driver_hs.drv_done = &drv_done_hs;
serial_driver_hs.configure = &SerialHsDrvConfigure;
serial_device_hs.hwdev_done = &hwdev_done_hs;
serial_cfg_hs.data_cfg = data_cfg_init;
serial_cfg_hs.hw_cfg.serial_register_base = UARTHS_BASE_ADDR;
serial_cfg_hs.hw_cfg.serial_irq_interrupt = IRQN_UARTHS_INTERRUPT;
serial_driver_hs.private_data = (void *)&serial_cfg_hs;
serial_dev_param_hs.serial_work_mode = SIGN_OPER_INT_RX;
serial_device_hs.haldev.private_data = (void *)&serial_dev_param_hs;
ret = BoardSerialBusInit(&serial_bus_hs, &serial_driver_hs, SERIAL_BUS_NAME_0, SERIAL_DRV_NAME_0);
if (EOK != ret) {
KPrintf("hw_serial_init uarths error ret %u\n", ret);
return ERROR;
}
ret = BoardSerialDevBend(&serial_device_hs, (void *)&serial_cfg_hs, SERIAL_BUS_NAME_0, SERIAL_0_DEVICE_NAME_0);
if (EOK != ret) {
KPrintf("hw_serial_init uarths error ret %u\n", ret);
return ERROR;
}
#endif
// #ifdef BSP_USING_UART1
// static struct SerialBus serial_bus_1;
// memset(&serial_bus_1, 0, sizeof(struct SerialBus));
// static struct SerialDriver serial_driver_1;
// memset(&serial_driver_1, 0, sizeof(struct SerialDriver));
// static struct SerialHardwareDevice serial_device_1;
// memset(&serial_device_1, 0, sizeof(struct SerialHardwareDevice));
// static struct SerialCfgParam serial_cfg_1;
// memset(&serial_cfg_1, 0, sizeof(struct SerialCfgParam));
// static struct SerialDevParam serial_dev_param_1;
// memset(&serial_dev_param_1, 0, sizeof(struct SerialDevParam));
// serial_driver_1.drv_done = &drv_done;
// serial_driver_1.configure = &SerialDrvConfigure;
// serial_device_1.hwdev_done = &hwdev_done;
// serial_cfg_1.data_cfg = data_cfg_init;
// serial_cfg_1.hw_cfg.serial_register_base = UART1_BASE_ADDR;
// serial_cfg_1.hw_cfg.serial_irq_interrupt = IRQN_UART1_INTERRUPT;
// serial_driver_1.private_data = (void *)&serial_cfg_1;
// serial_dev_param_1.serial_work_mode = SIGN_OPER_INT_RX;
// serial_device_1.haldev.private_data = (void *)&serial_dev_param_1;
// _uart_init_new(UART_DEVICE_1);
// ret = BoardSerialBusInit(&serial_bus_1, &serial_driver_1, SERIAL_BUS_NAME_1, SERIAL_DRV_NAME_1);
// if (EOK != ret) {
// KPrintf("hw_serial_init uart1 error ret %u\n", ret);
// return ERROR;
// }
// ret = BoardSerialDevBend(&serial_device_1, (void *)&serial_cfg_1, SERIAL_BUS_NAME_1, SERIAL_1_DEVICE_NAME_0);
// if (EOK != ret) {
// KPrintf("hw_serial_init uart1 error ret %u\n", ret);
// return ERROR;
// }
// #endif
// #ifdef BSP_USING_UART2
// static struct SerialBus serial_bus_2;
// memset(&serial_bus_2, 0, sizeof(struct SerialBus));
// static struct SerialDriver serial_driver_2;
// memset(&serial_driver_2, 0, sizeof(struct SerialDriver));
// static struct SerialHardwareDevice serial_device_2;
// memset(&serial_device_2, 0, sizeof(struct SerialHardwareDevice));
// static struct SerialCfgParam serial_cfg_2;
// memset(&serial_cfg_2, 0, sizeof(struct SerialCfgParam));
// static struct SerialDevParam serial_dev_param_2;
// memset(&serial_dev_param_2, 0, sizeof(struct SerialDevParam));
// serial_driver_2.drv_done = &drv_done;
// serial_driver_2.configure = &SerialDrvConfigure;
// serial_device_2.hwdev_done = &hwdev_done;
// serial_cfg_2.data_cfg = data_cfg_init;
// serial_cfg_2.hw_cfg.serial_register_base = UART2_BASE_ADDR;
// serial_cfg_2.hw_cfg.serial_irq_interrupt = IRQN_UART2_INTERRUPT;
// serial_driver_2.private_data = (void *)&serial_cfg_2;
// serial_dev_param_2.serial_work_mode = SIGN_OPER_INT_RX;
// serial_device_2.haldev.private_data = (void *)&serial_dev_param_2;
// _uart_init_new(UART_DEVICE_2);
// ret = BoardSerialBusInit(&serial_bus_2, &serial_driver_2, SERIAL_BUS_NAME_2, SERIAL_DRV_NAME_2);
// if (EOK != ret) {
// KPrintf("hw_serial_init uart2 error ret %u\n", ret);
// return ERROR;
// }
// ret = BoardSerialDevBend(&serial_device_2, (void *)&serial_cfg_2, SERIAL_BUS_NAME_2, SERIAL_2_DEVICE_NAME_0);
// if (EOK != ret) {
// KPrintf("hw_serial_init uart2 error ret %u\n", ret);
// return ERROR;
// }
// #endif
// #ifdef BSP_USING_UART3
// static struct SerialBus serial_bus_3;
// memset(&serial_bus_3, 0, sizeof(struct SerialBus));
// static struct SerialDriver serial_driver_3;
// memset(&serial_driver_3, 0, sizeof(struct SerialDriver));
// static struct SerialHardwareDevice serial_device_3;
// memset(&serial_device_3, 0, sizeof(struct SerialHardwareDevice));
// static struct SerialCfgParam serial_cfg_3;
// memset(&serial_cfg_3, 0, sizeof(struct SerialCfgParam));
// static struct SerialDevParam serial_dev_param_3;
// memset(&serial_dev_param_3, 0, sizeof(struct SerialDevParam));
// serial_driver_3.drv_done = &drv_done;
// serial_driver_3.configure = &SerialDrvConfigure;
// serial_device_3.hwdev_done = &hwdev_done;
// serial_cfg_3.data_cfg = data_cfg_init;
// serial_cfg_3.hw_cfg.serial_register_base = UART3_BASE_ADDR;
// serial_cfg_3.hw_cfg.serial_irq_interrupt = IRQN_UART3_INTERRUPT;
// serial_driver_3.private_data = (void *)&serial_cfg_3;
// serial_dev_param_3.serial_work_mode = SIGN_OPER_INT_RX;
// serial_device_3.haldev.private_data = (void *)&serial_dev_param_3;
// _uart_init_new(UART_DEVICE_3);
// ret = BoardSerialBusInit(&serial_bus_3, &serial_driver_3, SERIAL_BUS_NAME_3, SERIAL_DRV_NAME_3);
// if (EOK != ret) {
// KPrintf("hw_serial_init uart3 error ret %u\n", ret);
// return ERROR;
// }
// ret = BoardSerialDevBend(&serial_device_3, (void *)&serial_cfg_3, SERIAL_BUS_NAME_3, SERIAL_3_DEVICE_NAME_0);
// if (EOK != ret) {
// KPrintf("hw_serial_init uart3 error ret %u\n", ret);
// return ERROR;
// }
// #endif
return ret;
}

View File

@ -0,0 +1,424 @@
/* Copyright 2018 Canaan Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* @file hardware_uart.c
* @brief add from Canaan k210 SDK
* https://canaan-creative.com/developer
* @version 1.0
* @author AIIT XUOS Lab
* @date 2021-04-25
*/
#include <stdlib.h>
#include <stdint.h>
#include "plic.h"
#include "sysctl.h"
#include "hardware_uart.h"
#include "utils.h"
#include "atomic.h"
#define __UART_BRATE_CONST 16
volatile UartT* const uart[3] =
{
(volatile UartT*)UART1_BASE_ADDR,
(volatile UartT*)UART2_BASE_ADDR,
(volatile UartT*)UART3_BASE_ADDR
};
#define UART_INTERRUPT_SEND 0x02U
#define UART_INTERRUPT_RECEIVE 0x04U
#define UART_INTERRUPT_CHARACTER_TIMEOUT 0x0CU
typedef struct UartInterruptInstance
{
plic_irq_callback_t callback;
void *ctx;
} UartInterruptInstanceT;
typedef struct UartInstance
{
UartInterruptInstanceT UartReceiveInstance;
UartInterruptInstanceT UartSendInstance;
uint32_t UartNum;
} UartInstancePointer;
UartInstancePointer GUartInstance[3];
typedef struct UartDmaInstance
{
uint8_t *buffer;
size_t BufLen;
uint32_t *MallocBuffer;
UartInterruptModeT IntMode;
dmac_channel_number_t dmac_channel;
UartDeviceNumberT UartNum;
UartInterruptInstanceT UartIntInstance;
} UartDmaInstanceT;
UartDmaInstanceT uart_send_dma_instance[3];
UartDmaInstanceT UartRecvDmaInstance[3];
typedef struct UartInstanceDma
{
UartDeviceNumberT UartNum;
UartInterruptModeT TransferMode;
dmac_channel_number_t dmac_channel;
plic_instance_t UartIntInstance;
spinlock_t lock;
} UartInstanceDmaT;
static UartInstanceDmaT GUartSendInstanceDma[3];
static UartInstanceDmaT GUartRecvInstanceDma[3];
volatile int GWriteCount = 0;
static int UartIrqCallback(void *param)
{
UartInstancePointer *uart_instance = (UartInstancePointer *)param;
uint32_t v_channel = uart_instance->UartNum;
uint8_t VIntStatus = uart[v_channel]->IIR & 0xF;
if(VIntStatus == UART_INTERRUPT_SEND && GWriteCount != 0)
{
if(uart_instance->UartSendInstance.callback != NULL)
uart_instance->UartSendInstance.callback(uart_instance->UartSendInstance.ctx);
}
else if(VIntStatus == UART_INTERRUPT_RECEIVE || VIntStatus == UART_INTERRUPT_CHARACTER_TIMEOUT)
{
if(uart_instance->UartReceiveInstance.callback != NULL)
uart_instance->UartReceiveInstance.callback(uart_instance->UartReceiveInstance.ctx);
}
return 0;
}
static int UartapbPutc(UartDeviceNumberT channel, char c)
{
while (uart[channel]->LSR & (1u << 5))
continue;
uart[channel]->THR = c;
return 0;
}
int UartapbGetc(UartDeviceNumberT channel)
{
while (!(uart[channel]->LSR & 1))
continue;
return (char)(uart[channel]->RBR & 0xff);
}
static int UartDmaCallback(void *ctx)
{
UartDmaInstanceT *VUartDmaInstance = (UartDmaInstanceT *)ctx;
dmac_channel_number_t dmac_channel = VUartDmaInstance->dmac_channel;
dmac_irq_unregister(dmac_channel);
if(VUartDmaInstance->IntMode == UART_RECEIVE)
{
size_t VBufLen = VUartDmaInstance->BufLen;
uint8_t *VBuffer = VUartDmaInstance->buffer;
uint32_t *VRecvBuffer = VUartDmaInstance->MallocBuffer;
for(size_t i = 0; i < VBufLen; i++)
{
VBuffer[i] = VRecvBuffer[i];
}
}
free(VUartDmaInstance->MallocBuffer);
if(VUartDmaInstance->UartIntInstance.callback)
VUartDmaInstance->UartIntInstance.callback(VUartDmaInstance->UartIntInstance.ctx);
return 0;
}
int UartReceiveData(UartDeviceNumberT channel, char *buffer, size_t BufLen)
{
size_t i = 0;
for(i = 0;i < BufLen; i++)
{
if(uart[channel]->LSR & 1)
buffer[i] = (char)(uart[channel]->RBR & 0xff);
else
break;
}
return i;
}
void UartReceiveDataDma(UartDeviceNumberT uart_channel, dmac_channel_number_t dmac_channel, uint8_t *buffer, size_t BufLen)
{
uint32_t *VRecvBuf = malloc(BufLen * sizeof(uint32_t));
configASSERT(VRecvBuf!=NULL);
sysctl_dma_select((sysctl_dma_channel_t)dmac_channel, SYSCTL_DMA_SELECT_UART1_RX_REQ + uart_channel * 2);
dmac_set_single_mode(dmac_channel, (void *)(&uart[uart_channel]->RBR), VRecvBuf, DMAC_ADDR_NOCHANGE, DMAC_ADDR_INCREMENT,
DMAC_MSIZE_1, DMAC_TRANS_WIDTH_32, BufLen);
dmac_wait_done(dmac_channel);
for(uint32_t i = 0; i < BufLen; i++)
{
buffer[i] = (uint8_t)(VRecvBuf[i] & 0xff);
}
free(VRecvBuf);
}
void UartReceiveDataDmaIrq(UartDeviceNumberT uart_channel, dmac_channel_number_t dmac_channel,
uint8_t *buffer, size_t BufLen, plic_irq_callback_t uart_callback,
void *ctx, uint32_t priority)
{
uint32_t *VRecvBuf = malloc(BufLen * sizeof(uint32_t));
configASSERT(VRecvBuf!=NULL);
UartRecvDmaInstance[uart_channel].dmac_channel = dmac_channel;
UartRecvDmaInstance[uart_channel].UartNum = uart_channel;
UartRecvDmaInstance[uart_channel].MallocBuffer = VRecvBuf;
UartRecvDmaInstance[uart_channel].buffer = buffer;
UartRecvDmaInstance[uart_channel].BufLen = BufLen;
UartRecvDmaInstance[uart_channel].IntMode = UART_RECEIVE;
UartRecvDmaInstance[uart_channel].UartIntInstance.callback = uart_callback;
UartRecvDmaInstance[uart_channel].UartIntInstance.ctx = ctx;
dmac_irq_register(dmac_channel, UartDmaCallback, &UartRecvDmaInstance[uart_channel], priority);
sysctl_dma_select((sysctl_dma_channel_t)dmac_channel, SYSCTL_DMA_SELECT_UART1_RX_REQ + uart_channel * 2);
dmac_set_single_mode(dmac_channel, (void *)(&uart[uart_channel]->RBR), VRecvBuf, DMAC_ADDR_NOCHANGE, DMAC_ADDR_INCREMENT,
DMAC_MSIZE_1, DMAC_TRANS_WIDTH_32, BufLen);
}
int UartSendData(UartDeviceNumberT channel, const char *buffer, size_t BufLen)
{
GWriteCount = 0;
while (GWriteCount < BufLen)
{
UartapbPutc(channel, *buffer++);
GWriteCount++;
}
return GWriteCount;
}
void UartSendDataDma(UartDeviceNumberT uart_channel, dmac_channel_number_t dmac_channel, const uint8_t *buffer, size_t BufLen)
{
uint32_t *VSendBuf = malloc(BufLen * sizeof(uint32_t));
configASSERT(VSendBuf!=NULL);
for(uint32_t i = 0; i < BufLen; i++)
VSendBuf[i] = buffer[i];
sysctl_dma_select((sysctl_dma_channel_t)dmac_channel, SYSCTL_DMA_SELECT_UART1_TX_REQ + uart_channel * 2);
dmac_set_single_mode(dmac_channel, VSendBuf, (void *)(&uart[uart_channel]->THR), DMAC_ADDR_INCREMENT, DMAC_ADDR_NOCHANGE,
DMAC_MSIZE_1, DMAC_TRANS_WIDTH_32, BufLen);
dmac_wait_done(dmac_channel);
free((void *)VSendBuf);
}
void UartSendDataDmaIrq(UartDeviceNumberT uart_channel, dmac_channel_number_t dmac_channel,
const uint8_t *buffer, size_t BufLen, plic_irq_callback_t uart_callback,
void *ctx, uint32_t priority)
{
uint32_t *VSendBuf = malloc(BufLen * sizeof(uint32_t));
configASSERT(VSendBuf!=NULL);
uart_send_dma_instance[uart_channel] = (UartDmaInstanceT) {
.dmac_channel = dmac_channel,
.UartNum = uart_channel,
.MallocBuffer = VSendBuf,
.buffer = (uint8_t *)buffer,
.BufLen = BufLen,
.IntMode = UART_SEND,
.UartIntInstance.callback = uart_callback,
.UartIntInstance.ctx = ctx,
};
for(uint32_t i = 0; i < BufLen; i++)
VSendBuf[i] = buffer[i];
dmac_irq_register(dmac_channel, UartDmaCallback, &uart_send_dma_instance[uart_channel], priority);
sysctl_dma_select((sysctl_dma_channel_t)dmac_channel, SYSCTL_DMA_SELECT_UART1_TX_REQ + uart_channel * 2);
dmac_set_single_mode(dmac_channel, VSendBuf, (void *)(&uart[uart_channel]->THR), DMAC_ADDR_INCREMENT, DMAC_ADDR_NOCHANGE,
DMAC_MSIZE_1, DMAC_TRANS_WIDTH_32, BufLen);
}
void uart_configure(UartDeviceNumberT channel, uint32_t BaudRate, UartBitwidthPointer DataWidth, UartStopbitT stopbit, UartParityT parity)
{
configASSERT(DataWidth >= 5 && DataWidth <= 8);
if (DataWidth == 5)
{
configASSERT(stopbit != UART_STOP_2);
}
else
{
configASSERT(stopbit != UART_STOP_1_5);
}
uint32_t stopbit_val = stopbit == UART_STOP_1 ? 0 : 1;
uint32_t ParityVal;
switch (parity)
{
case UART_PARITY_NONE:
ParityVal = 0;
break;
case UART_PARITY_ODD:
ParityVal = 1;
break;
case UART_PARITY_EVEN:
ParityVal = 3;
break;
default:
configASSERT(!"Invalid parity");
break;
}
uint32_t freq = SysctlClockGetFreq(SYSCTL_CLOCK_APB0);
uint32_t divisor = freq / BaudRate;
uint8_t dlh = divisor >> 12;
uint8_t dll = (divisor - (dlh << 12)) / __UART_BRATE_CONST;
uint8_t dlf = divisor - (dlh << 12) - dll * __UART_BRATE_CONST;
/* Set UART registers */
uart[channel]->TCR &= ~(1u);
uart[channel]->TCR &= ~(1u << 3);
uart[channel]->TCR &= ~(1u << 4);
uart[channel]->TCR |= (1u << 2);
uart[channel]->TCR &= ~(1u << 1);
uart[channel]->DE_EN &= ~(1u);
uart[channel]->LCR |= 1u << 7;
uart[channel]->DLH = dlh;
uart[channel]->DLL = dll;
uart[channel]->DLF = dlf;
uart[channel]->LCR = 0;
uart[channel]->LCR = (DataWidth - 5) | (stopbit_val << 2) | (ParityVal << 3);
uart[channel]->LCR &= ~(1u << 7);
uart[channel]->MCR &= ~3;
uart[channel]->IER |= 0x80; /* THRE */
uart[channel]->FCR = UART_RECEIVE_FIFO_1 << 6 | UART_SEND_FIFO_8 << 4 | 0x1 << 3 | 0x1;
}
void __attribute__((weak, alias("uart_configure")))
uart_config(UartDeviceNumberT channel, uint32_t BaudRate, UartBitwidthPointer DataWidth, UartStopbitT stopbit, UartParityT parity);
void UartInit(UartDeviceNumberT channel)
{
sysctl_clock_enable(SYSCTL_CLOCK_UART1 + channel);
}
void UartSetSendTrigger(UartDeviceNumberT channel, uart_send_trigger_t trigger)
{
uart[channel]->STET = trigger;
}
void uart_set_receive_trigger(UartDeviceNumberT channel, uart_receive_trigger_t trigger)
{
uart[channel]->SRT = trigger;
}
void uart_irq_register(UartDeviceNumberT channel, UartInterruptModeT interrupt_mode, plic_irq_callback_t uart_callback, void *ctx, uint32_t priority)
{
if(interrupt_mode == UART_SEND)
{
uart[channel]->IER |= 0x2;
GUartInstance[channel].UartSendInstance.callback = uart_callback;
GUartInstance[channel].UartSendInstance.ctx = ctx;
}
else if(interrupt_mode == UART_RECEIVE)
{
uart[channel]->IER |= 0x1;
GUartInstance[channel].UartReceiveInstance.callback = uart_callback;
GUartInstance[channel].UartReceiveInstance.ctx = ctx;
}
GUartInstance[channel].UartNum = channel;
plic_set_priority(IRQN_UART1_INTERRUPT + channel, priority);
plic_irq_register(IRQN_UART1_INTERRUPT + channel, UartIrqCallback, &GUartInstance[channel]);
plic_irq_enable(IRQN_UART1_INTERRUPT + channel);
}
void uart_irq_unregister(UartDeviceNumberT channel, UartInterruptModeT interrupt_mode)
{
if(interrupt_mode == UART_SEND)
{
uart[channel]->IER &= ~(0x2);
GUartInstance[channel].UartSendInstance.callback = NULL;
GUartInstance[channel].UartSendInstance.ctx = NULL;
}
else if(interrupt_mode == UART_RECEIVE)
{
uart[channel]->IER &= ~(0x1);
GUartInstance[channel].UartReceiveInstance.callback = NULL;
GUartInstance[channel].UartReceiveInstance.ctx = NULL;
}
if(uart[channel]->IER == 0)
{
plic_irq_unregister(IRQN_UART1_INTERRUPT + channel);
}
}
int uart_dma_irq(void *ctx)
{
UartInstanceDmaT *v_instance = (UartInstanceDmaT *)ctx;
dmac_irq_unregister(v_instance->dmac_channel);
if(v_instance->TransferMode == UART_SEND)
{
while(!(uart[v_instance->UartNum]->LSR & (1u << 6)));
}
spinlock_unlock(&v_instance->lock);
if(v_instance->UartIntInstance.callback)
{
v_instance->UartIntInstance.callback(v_instance->UartIntInstance.ctx);
}
return 0;
}
void uart_handle_data_dma(UartDeviceNumberT uart_channel ,uart_data_t data, plic_interrupt_t *cb)
{
configASSERT(uart_channel < UART_DEVICE_MAX);
if(data.TransferMode == UART_SEND)
{
configASSERT(data.tx_buf && data.tx_len && data.tx_channel < DMAC_CHANNEL_MAX);
spinlock_lock(&GUartSendInstanceDma[uart_channel].lock);
if(cb)
{
GUartSendInstanceDma[uart_channel].UartIntInstance.callback = cb->callback;
GUartSendInstanceDma[uart_channel].UartIntInstance.ctx = cb->ctx;
GUartSendInstanceDma[uart_channel].dmac_channel = data.tx_channel;
GUartSendInstanceDma[uart_channel].TransferMode = UART_SEND;
dmac_irq_register(data.tx_channel, uart_dma_irq, &GUartSendInstanceDma[uart_channel], cb->priority);
}
sysctl_dma_select((sysctl_dma_channel_t)data.tx_channel, SYSCTL_DMA_SELECT_UART1_TX_REQ + uart_channel * 2);
dmac_set_single_mode(data.tx_channel, data.tx_buf, (void *)(&uart[uart_channel]->THR), DMAC_ADDR_INCREMENT, DMAC_ADDR_NOCHANGE,
DMAC_MSIZE_1, DMAC_TRANS_WIDTH_32, data.tx_len);
if(!cb)
{
dmac_wait_done(data.tx_channel);
while(!(uart[uart_channel]->LSR & (1u << 6)));
spinlock_unlock(&GUartSendInstanceDma[uart_channel].lock);
}
}
else
{
configASSERT(data.rx_buf && data.rx_len && data.rx_channel < DMAC_CHANNEL_MAX);
spinlock_lock(&GUartRecvInstanceDma[uart_channel].lock);
if(cb)
{
GUartRecvInstanceDma[uart_channel].UartIntInstance.callback = cb->callback;
GUartRecvInstanceDma[uart_channel].UartIntInstance.ctx = cb->ctx;
GUartRecvInstanceDma[uart_channel].dmac_channel = data.rx_channel;
GUartRecvInstanceDma[uart_channel].TransferMode = UART_RECEIVE;
dmac_irq_register(data.rx_channel, uart_dma_irq, &GUartRecvInstanceDma[uart_channel], cb->priority);
}
sysctl_dma_select((sysctl_dma_channel_t)data.rx_channel, SYSCTL_DMA_SELECT_UART1_RX_REQ + uart_channel * 2);
dmac_set_single_mode(data.rx_channel, (void *)(&uart[uart_channel]->RBR), data.rx_buf, DMAC_ADDR_NOCHANGE, DMAC_ADDR_INCREMENT,
DMAC_MSIZE_1, DMAC_TRANS_WIDTH_32, data.rx_len);
if(!cb)
{
dmac_wait_done(data.rx_channel);
spinlock_unlock(&GUartRecvInstanceDma[uart_channel].lock);
}
}
}

View File

@ -0,0 +1,184 @@
/* Copyright 2018 Canaan Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* @file hardware_uarths.c
* @brief add from Canaan k210 SDK
* https://canaan-creative.com/developer
* @version 1.0
* @author AIIT XUOS Lab
* @date 2021-04-25
*/
#include <stdint.h>
#include <stdio.h>
#include "hardware_uarths.h"
#include "sysctl.h"
#include "encoding.h"
volatile UarthsT *const uarths = (volatile UarthsT *)UARTHS_BASE_ADDR;
typedef struct _uarths_instance
{
plic_irq_callback_t callback;
void *ctx;
uarths_interrupt_mode_t uarths_interrupt_mode;
} uarths_instance_t;
uarths_instance_t g_uarths_instance;
uarths_interrupt_mode_t uarths_get_interrupt_mode(void)
{
uint32_t v_rx_interrupt = uarths->ip.rxwm;
uint32_t v_tx_interrupt = uarths->ip.txwm;
return (v_rx_interrupt << 1) | v_tx_interrupt;
}
int uarths_irq_callback(void *ctx)
{
uarths_instance_t *uart_context = (uarths_instance_t *)ctx;
if(uart_context->callback)
uart_context->callback(uart_context->ctx);
return 0;
}
void uarths_set_interrupt_cnt(uarths_interrupt_mode_t interrupt_mode, uint8_t cnt)
{
switch(interrupt_mode)
{
case UARTHS_SEND:
uarths->txctrl.txcnt = cnt;
break;
case UARTHS_RECEIVE:
uarths->rxctrl.rxcnt = cnt;
break;
case UARTHS_SEND_RECEIVE:
default:
uarths->txctrl.txcnt = cnt;
uarths->rxctrl.rxcnt = cnt;
break;
}
}
void uarths_set_irq(uarths_interrupt_mode_t interrupt_mode, plic_irq_callback_t uarths_callback, void *ctx, uint32_t priority)
{
g_uarths_instance.callback = uarths_callback;
g_uarths_instance.ctx = ctx;
switch(interrupt_mode)
{
case UARTHS_SEND:
uarths->ie.txwm = 1;
uarths->ie.rxwm = 0;
break;
case UARTHS_RECEIVE:
uarths->ie.txwm = 0;
uarths->ie.rxwm = 1;
break;
default:
uarths->ie.txwm = 1;
uarths->ie.rxwm = 1;
break;
}
g_uarths_instance.uarths_interrupt_mode = interrupt_mode;
plic_set_priority(IRQN_UARTHS_INTERRUPT, priority);
plic_irq_register(IRQN_UARTHS_INTERRUPT, uarths_irq_callback, &g_uarths_instance);
plic_irq_enable(IRQN_UARTHS_INTERRUPT);
}
static inline int uarths_putc(char c)
{
while (uarths->txdata.full)
continue;
uarths->txdata.data = (uint8_t)c;
return 0;
}
size_t uarths_receive_data(uint8_t *buf, size_t BufLen)
{
size_t i;
for(i = 0; i < BufLen; i++)
{
uarths_rxdata_t recv = uarths->rxdata;
if(recv.empty)
break;
else
buf[i] = (recv.data & 0xFF);
}
return i;
}
size_t uarths_send_data(const uint8_t *buf, size_t BufLen)
{
size_t write = 0;
while (write < BufLen)
{
uarths_putc(*buf++);
write++;
}
return write;
}
int uarths_getc(void)
{
/* while not empty */
uarths_rxdata_t recv = uarths->rxdata;
if (recv.empty)
return EOF;
else
return recv.data;
}
int uarths_putchar(char c)
{
return uarths_putc(c);
}
int uarths_puts(const char *s)
{
while (*s)
if (uarths_putc(*s++) != 0)
return -1;
return 0;
}
void uarths_init(void)
{
uint32_t freq = SysctlClockGetFreq(SYSCTL_CLOCK_CPU);
uint16_t div = freq / 115200 - 1;
/* Set UART registers */
uarths->div.div = div;
uarths->txctrl.txen = 1;
uarths->rxctrl.rxen = 1;
uarths->txctrl.txcnt = 0;
uarths->rxctrl.rxcnt = 0;
uarths->ip.txwm = 1;
uarths->ip.rxwm = 1;
uarths->ie.txwm = 0;
uarths->ie.rxwm = 1;
}
void uarths_config(uint32_t BaudRate, uarths_stopbit_t stopbit)
{
uint32_t freq = SysctlClockGetFreq(SYSCTL_CLOCK_CPU);
uint16_t div = freq / BaudRate - 1;
uarths->div.div = div;
uarths->txctrl.nstop = stopbit;
}

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