forked from xuos/xiuos
feat modify XiUOS_Kernel dir from Ubiquitous/XiUOS to Ubiquitous/XiZi
This commit is contained in:
@@ -0,0 +1,234 @@
|
||||
#
|
||||
# Automatically generated file; DO NOT EDIT.
|
||||
# XiZi Project Configuration
|
||||
#
|
||||
CONFIG_BOARD_MAIX_GO_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
|
||||
|
||||
#
|
||||
# spieed maix go 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_COLOR=y
|
||||
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
|
||||
#
|
||||
|
||||
#
|
||||
# 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
|
||||
#
|
||||
@@ -0,0 +1,57 @@
|
||||
mainmenu "XiZi Project Configuration"
|
||||
|
||||
config BSP_DIR
|
||||
string
|
||||
option env="BSP_ROOT"
|
||||
default "."
|
||||
|
||||
config KERNEL_DIR
|
||||
string
|
||||
option env="KERNEL_ROOT"
|
||||
default "../.."
|
||||
|
||||
config BOARD_MAIX_GO_EVB
|
||||
bool
|
||||
select ARCH_RISCV
|
||||
select ARCH_RISCV64
|
||||
select ARCH_CPU_64BIT
|
||||
default y
|
||||
|
||||
source "$KERNEL_DIR/arch/Kconfig"
|
||||
|
||||
|
||||
menu "spieed maix go 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_maix-go_app.bin"
|
||||
endmenu
|
||||
|
||||
menu "config board service table"
|
||||
config SERVICE_TABLE_ADDRESS
|
||||
hex "board service table address"
|
||||
default 0x80100000
|
||||
endmenu
|
||||
|
||||
endmenu
|
||||
|
||||
config __STACKSIZE__
|
||||
int "stack size for interrupt"
|
||||
default 4096
|
||||
|
||||
endmenu
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
menu "Hardware feature"
|
||||
source "$KERNEL_DIR/resources/Kconfig"
|
||||
endmenu
|
||||
|
||||
source "$KERNEL_DIR/Kconfig"
|
||||
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
SRC_FILES := board.c
|
||||
|
||||
SRC_DIR := third_party_driver
|
||||
|
||||
|
||||
include $(KERNEL_ROOT)/compiler.mk
|
||||
@@ -0,0 +1,71 @@
|
||||
# maix-go README
|
||||
|
||||
## 1. 简介
|
||||
|
||||
| 硬件 | 描述 |
|
||||
| -- | -- |
|
||||
|芯片型号| K210 |
|
||||
|CPU| 双核RV64GC |
|
||||
|主频| 400MHz |
|
||||
|片内SRAM| 8MB |
|
||||
| 外设 | 内嵌AES与SHA256算法加速器 |
|
||||
| | DVP、JTAG、OTP、FPIOA、GPIO、UART、SPI、RTC、I²S、I²C、WDT、Timer与PWM |
|
||||
|
||||
XiUOS板级当前支持使用GPIO、UART等。
|
||||
|
||||
## 2. 编译说明
|
||||
|
||||
编译环境:Ubuntu18.04
|
||||
|
||||
编译工具链:[riscv-none-embed-gcc](https://github.com/ilg-archived/riscv-none-gcc/releases)
|
||||
|
||||
编译步骤:
|
||||
|
||||
>1.将编译工具链的路径添加到board/maix-go/config.mk文件当中,例如将gnu-mcu-eclipse-riscv-none-gcc-8.2.0-2.1-20190425-1021-centos64.tgz解压到/opt/下时添加:
|
||||
```
|
||||
export CROSS_COMPILE ?=/opt/gnu-mcu-eclipse/riscv-none-gcc/8.2.0-2.1-20190425-1021/bin/riscv-none-embed-
|
||||
```
|
||||
>2.在代码根目录下执行以下命令,生成配置文件
|
||||
```
|
||||
make BOARD=maix-go menuconfig
|
||||
```
|
||||
>3.在menuconfig界面配置需要关闭和开启的功能,按回车键进入下级菜单,按Y键选中需要开启的功能,按N键选中需要关闭的功能,配置结束后选择Exit保存并退出
|
||||
>4.继续执行以下命令,进行编译
|
||||
```
|
||||
make BOARD=maix-go
|
||||
```
|
||||
>5.如果编译正确无误,会产生XiUOS_maix-go.elf、XiUOS_maix-go.bin文件。其中XiUOS_maix-go.bin需要烧写到设备中进行运行。
|
||||
>注:最后可以执行以下命令,清除配置文件和编译生成的文件
|
||||
```
|
||||
make BOARD=maix-go distclean
|
||||
```
|
||||
|
||||
## 3. 烧写及执行
|
||||
|
||||
连接开发板串口(即Type-C口)到USB接口,拨动开发板电源开关,然后使用K-Flash工具进行烧写bin文件。
|
||||
|
||||

|
||||
|
||||
执行以下命令安装K-Flash工具
|
||||
```
|
||||
sudo apt install python3 python3-pip
|
||||
sudo pip3 install pyserial
|
||||
sudo pip3 install pyelftools
|
||||
sudo pip3 install kflash
|
||||
```
|
||||
如果最后一步安装kflash出现错误,可以尝试以下命令
|
||||
```
|
||||
sudo python -m pip install kflash
|
||||
sudo python3 -m pip install kflash
|
||||
sudo pip install kflash
|
||||
sudo pip2 install kflash
|
||||
```
|
||||
代码根目录下执行K-Flash工具烧录,此时ls /dev/ttyUSB*会发现新增2个USB端口,烧录时选择后一个,例如此时新增的是/dev/ttyUSB0和/dev/ttyUSB1,选择/dev/ttyUSB1
|
||||
```
|
||||
kflash -t build/XiUOS_kd233.bin -p /dev/ttyUSB1
|
||||
```
|
||||
### 3.1 运行结果
|
||||
|
||||
如果编译 & 烧写无误,将会在串口终端上看到信息打印输出。
|
||||
|
||||

|
||||
@@ -0,0 +1,177 @@
|
||||
/* 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 maix-go-board init configure and start-up
|
||||
* @version 1.0
|
||||
* @author AIIT XUOS Lab
|
||||
* @date 2021-04-25
|
||||
*/
|
||||
|
||||
/*************************************************
|
||||
File name: board.c
|
||||
Description: support maix-go-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 maix-go-board InitBoardHardware
|
||||
2. support maix-go-board Kd233Start
|
||||
3. support maix-go-board shell cmd, include reboot, shutdown
|
||||
*************************************************/
|
||||
|
||||
#include <xizi.h>
|
||||
#include <clint.h>
|
||||
#include <sysctl.h>
|
||||
#include "board.h"
|
||||
#include "tick.h"
|
||||
#include "connect_uart.h"
|
||||
#include "encoding.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 int IoConfigInit(void);
|
||||
extern int HwSpiInit(void);
|
||||
extern int HwI2cInit(void);
|
||||
extern int HwRtcInit(void);
|
||||
extern int HwWdtInit(void);
|
||||
extern int HwLcdInit(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;
|
||||
case CPU1:
|
||||
while(0x2018050420191010 != cpu2_boot_flag) { ///< waiting for boot flag ,then start cpu1 core
|
||||
#ifndef ARCH_SMP
|
||||
asm volatile("wfi");
|
||||
#endif
|
||||
}
|
||||
#ifdef ARCH_SMP
|
||||
SecondaryCpuCStart();
|
||||
#endif
|
||||
break;
|
||||
|
||||
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 frequency information );
|
||||
|
||||
#ifdef ARCH_SMP
|
||||
extern int EnableHwclintIpi(void);
|
||||
#endif
|
||||
|
||||
|
||||
void InitBoardHardware(void)
|
||||
{
|
||||
int i = 0;
|
||||
int ret = 0;
|
||||
|
||||
SysctlPllSetFreq(SYSCTL_PLL0, 800000000UL);
|
||||
SysctlPllSetFreq(SYSCTL_PLL1, 400000000UL);
|
||||
#ifdef BSP_USING_GPIO
|
||||
/* Init FPIOA */
|
||||
FpioaInit();
|
||||
#endif
|
||||
#ifdef BSP_USING_DMA
|
||||
/* Dmac init */
|
||||
DmacInit();
|
||||
#endif
|
||||
/* 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);
|
||||
|
||||
|
||||
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 );
|
||||
|
||||
|
||||
@@ -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 maix-go-board init configure and start-up function
|
||||
* @version 1.0
|
||||
* @author AIIT XUOS Lab
|
||||
* @date 2021-04-25
|
||||
*/
|
||||
|
||||
/*************************************************
|
||||
File name: board.h
|
||||
Description: define maix-go-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 maix-go-board InitBoardHardware
|
||||
2. define maix-go-board data and bss struct
|
||||
*************************************************/
|
||||
|
||||
#ifndef BOARD_H__
|
||||
#define BOARD_H__
|
||||
|
||||
#include <xsconfig.h>
|
||||
#include <stdint.h>
|
||||
#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
|
||||
@@ -0,0 +1,19 @@
|
||||
export CFLAGS := -mcmodel=medany -march=rv64imafdc -mabi=lp64d -fno-common -ffunction-sections -fdata-sections -fstrict-volatile-bitfields -O0 -ggdb -fgnu89-inline -Werror
|
||||
export AFLAGS := -c -mcmodel=medany -march=rv64imafdc -mabi=lp64d -x assembler-with-cpp -ggdb
|
||||
export LFLAGS := -mcmodel=medany -march=rv64imafdc -mabi=lp64d -nostartfiles -Wl,--gc-sections,-Map=XiZi.map,-cref,-u,_start -T $(BSP_ROOT)/link.lds
|
||||
|
||||
export APPLFLAGS := -mcmodel=medany -march=rv64imafdc -mabi=lp64d -nostartfiles -Wl,--gc-sections,-Map=XiZi_app.map,-cref,-u, -T $(BSP_ROOT)/link_userspace.lds
|
||||
|
||||
export CXXFLAGS := -mcmodel=medany -march=rv64imafdc -mabi=lp64d -fno-common -ffunction-sections -fdata-sections -fstrict-volatile-bitfields -O0 -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
|
||||
|
||||
# export HAVE_SIGINFO=1
|
||||
|
||||
# export USING_LORA = 1
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
After Width: | Height: | Size: 61 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 40 KiB |
@@ -0,0 +1,254 @@
|
||||
|
||||
/* 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 */
|
||||
|
||||
@@ -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
|
||||
@@ -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
@@ -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 init_bss(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 */
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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 (0x38000000U)
|
||||
#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 */
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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(.);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
/*
|
||||
* 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
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
|
||||
|
||||
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_UART
|
||||
bool "Using UART device"
|
||||
default y
|
||||
select RESOURCES_SERIAL
|
||||
if BSP_USING_UART
|
||||
source "$BSP_DIR/third_party_driver/uart/Kconfig"
|
||||
endif
|
||||
|
||||
|
||||
@@ -0,0 +1,65 @@
|
||||
SRC_FILES := sleep.c
|
||||
|
||||
ifeq ($(CONFIG_BSP_USING_AUDIO),y)
|
||||
SRC_DIR += audio
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_BSP_USING_CAMERA),y)
|
||||
SRC_DIR += camera
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_BSP_USING_DMA),y)
|
||||
SRC_DIR += dma
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_BSP_USING_GPIO),y)
|
||||
SRC_DIR += gpio
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_BSP_USING_I2C),y)
|
||||
SRC_DIR += i2c
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_BSP_USING_I2S),y)
|
||||
SRC_DIR += i2s
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_BSP_USING_LCD),y)
|
||||
SRC_DIR += lcd
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_BSP_USING_PLIC),y)
|
||||
SRC_DIR += plic
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_BSP_USING_RTC),y)
|
||||
SRC_DIR += rtc
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_BSP_USING_SECURITY),y)
|
||||
SRC_DIR += security
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_BSP_USING_SPI),y)
|
||||
SRC_DIR += spi
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_BSP_USING_SYSCLOCK),y)
|
||||
SRC_DIR += sys_clock
|
||||
endif
|
||||
|
||||
|
||||
|
||||
ifeq ($(CONFIG_BSP_USING_UART),y)
|
||||
SRC_DIR += uart
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_BSP_USING_VIDEO),y)
|
||||
SRC_DIR += video
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_BSP_USING_WDT),y)
|
||||
SRC_DIR += watchdog
|
||||
endif
|
||||
|
||||
include $(KERNEL_ROOT)/compiler.mk
|
||||
@@ -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 core’s 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 core’s time comparator. A timer interrupt is pending
|
||||
* whenever mtime is greater than or equal to the value in a
|
||||
* core’s mtimecmp register. The timer interrupt is reflected in
|
||||
* the mtip bit of the associated core’s 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__ */
|
||||
|
||||
@@ -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
|
||||
File diff suppressed because it is too large
Load Diff
@@ -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__ */
|
||||
@@ -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__ */
|
||||
@@ -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__ */
|
||||
@@ -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 = 33, /*!< 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 device’s interrupt can be
|
||||
* enabled by setting the corresponding bit in that target’s
|
||||
* 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 source’s 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 target’s 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 target’s 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
@@ -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 */
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
SRC_FILES := drv_interrupt.c plic.c clint.c
|
||||
|
||||
|
||||
|
||||
include $(KERNEL_ROOT)/compiler.mk
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
SRC_FILES := sysctl.c
|
||||
|
||||
|
||||
|
||||
|
||||
include $(KERNEL_ROOT)/compiler.mk
|
||||
File diff suppressed because it is too large
Load Diff
@@ -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
|
||||
@@ -0,0 +1,3 @@
|
||||
SRC_FILES := connect_uart.c
|
||||
|
||||
include $(KERNEL_ROOT)/compiler.mk
|
||||
@@ -0,0 +1,652 @@
|
||||
/*
|
||||
* Copyright (c) 2020 RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file connect_uart.c
|
||||
* @brief support maix-go-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 maix-go-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 maix-go-board uart configure, write and read
|
||||
2. support maix-go-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);
|
||||
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;
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
Reference in New Issue
Block a user