rel_1.6.0 init

This commit is contained in:
guocheng.kgc 2020-06-18 20:06:52 +08:00 committed by shengdong.dsd
commit 27b3e2883d
19359 changed files with 8093121 additions and 0 deletions

View file

@ -0,0 +1,27 @@
/*
* Copyright (C) 2017 C-SKY Microsystems Co., Ltd. All rights reserved.
*
* 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.
*/
## Usage
1. Download compiler:cskt_abiv2_elf-tool
* [CSKY ABIV ELF](https://pan.baidu.com/s/1nvKdhED passwd:62q6)
$ tar -zxf csky-abiv2-elf-tools-x86_64-minilibc-20160704.tar.gz -C build/compiler/
2. Compiling csky hobbit project
$ aos make helloworld@hobbit1_evb
3. initialize gdbinit
$ cp platform/mcu/csky/config/hobbit_gdbinit .gdbinit
4. download bin file to hobbit1_2 board by cds tool
5. run
$ csky-abiv2-elf-gdb out/helloworld@hobbit1_2/binary/helloworld@hobbit1_evb.elf

View file

@ -0,0 +1,69 @@
/*
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
*/
#include <aos/aos.h>
#include <k_api.h>
#include <aos/kernel.h>
#include <stdio.h>
#include <stdlib.h>
#define AOS_START_STACK 1536
extern void hal_init(void);
extern int lwip_tcpip_init(void);
ktask_t *g_aos_init;
krhino_err_proc_t g_err_proc = soc_err_proc;
size_t soc_get_cur_sp()
{
volatile size_t dummy = (size_t)&dummy;
return dummy;
}
#if (RHINO_CONFIG_HW_COUNT > 0)
hr_timer_t soc_hr_hw_cnt_get(void)
{
return 0;
}
#endif
#define HEAP_BUFFER_SIZE 1024*54
uint8_t g_heap_buf[HEAP_BUFFER_SIZE];
k_mm_region_t g_mm_region[] = {{g_heap_buf, HEAP_BUFFER_SIZE}};
int g_region_num = sizeof(g_mm_region) / sizeof(k_mm_region_t);
uint32_t __heap_start = (uint32_t)g_heap_buf;
uint32_t __heap_end = (uint32_t)(g_heap_buf + HEAP_BUFFER_SIZE);
void soc_err_proc(kstat_t err)
{
printf("kernel panic,err %d!\n", err);
}
static kinit_t kinit;
void board_cli_init(void)
{
kinit.argc = 0;
kinit.argv = NULL;
kinit.cli_enable = 1;
}
void sys_init_func(void)
{
//test_case_task_start();
hal_init();
board_cli_init();
lwip_tcpip_init();
aos_kernel_init(&kinit);
}
int main(void)
{
printf("alios start\n");
aos_init();
krhino_task_dyn_create(&g_aos_init, "aos-init", 0, 6, 0, AOS_START_STACK, (task_entry_t)sys_init_func, 1);
aos_start();
return 0;
}

View file

@ -0,0 +1,233 @@
/*
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
*/
#include <k_api.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/types.h>
#include <aos/network.h>
#include <hal/trace.h>
#include <aos/aos.h>
/* CLI Support */
#ifdef CONFIG_AOS_CLI
/* Trace Open*/
#if (RHINO_CONFIG_TRACE > 0)
#define TRACE_TASK_STACK_SIZE 512
extern struct k_fifo trace_fifo;
extern int32_t set_filter_task(const char * task_name);
extern void set_event_mask(const uint32_t mask);
extern void trace_deinit(void);
static ktask_t *trace_task;
static uint32_t trace_buf[1024];
static volatile int trace_is_started;
static char *filter_task;
static char *ip_addr;
static uint16_t ip_port = 8000;
static int sockfd;
void *trace_hal_init()
{
int fd;
struct sockaddr_in servaddr;
TRACE_INIT();
if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
aos_cli_printf("create socket (%s:%u) error: %s(errno: %d)\r\n", ip_addr, ip_port, strerror(errno),errno);
return 0;
}
memset(&servaddr, 0, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons(ip_port);
inet_aton(ip_addr, &servaddr.sin_addr);
if (connect(fd, (struct sockaddr*)&servaddr, sizeof(servaddr)) < 0) {
aos_cli_printf("connect (%s:%u) error: %s(errno: %d)\r\n", ip_addr, ip_port, strerror(errno),errno);
close(fd);
return 0;
}
aos_cli_printf("connected on (%s:%u)\r\n", ip_addr, ip_port);
return (void *)fd;
}
ssize_t trace_hal_send(void *handle, void *buf, size_t len)
{
int len_send = 0;
int len_total_send = 0;
while (1) {
len_send = send((int)handle, (buf + len_total_send) , len, 0);
if (len_send < 0) {
aos_cli_printf("send (%s:%u) msg error: %s(errno: %d)\r\n", ip_addr, ip_port, strerror(errno), errno);
return 0;
}
len_total_send += len_send;
len -= len_send;
if (len == 0) {
break;
}
}
return len_send;
}
ssize_t trace_hal_recv(void *handle, void *buf)
{
return 0;
}
void trace_hal_deinit(void *handle)
{
int fd;
fd = (int)handle;
close(fd);
*(int *)handle = -1;
sockfd = -1;
}
void trace_stop(void)
{
set_filter_task(NULL);
set_event_mask(0);
trace_deinit();
trace_hal_deinit((void *)sockfd);
aos_cli_printf("trace (%s:%u) stop....\r\n", ip_addr, ip_port);
if (ip_addr) {
aos_free(ip_addr);
ip_addr = NULL;
}
if (filter_task){
aos_free(filter_task);
filter_task = NULL;
}
}
static void trace_entry(void *arg)
{
uint32_t len;
while (1) {
if (trace_is_started == 0 ){
if (sockfd > 0) {
trace_stop();
}
krhino_task_sleep(200);
} else {
if (sockfd <= 0) {
sockfd = (int)trace_hal_init();
}
if (sockfd > 0) {
len = fifo_out_all(&trace_fifo, trace_buf);
if (len > 0) {
trace_hal_send((void *)sockfd, trace_buf, len);
}
}
krhino_task_sleep(20);
}
}
}
static void handle_trace_cmd(char *pwbuf, int blen, int argc, char **argv)
{
const char *rtype = argc > 1 ? argv[1] : "";
int ret = 0;
if (strcmp(rtype, "start") == 0) {
trace_is_started = 1;
if (argc == 3 || argc == 4) {
if (ip_addr == NULL) {
ip_addr = (char *) aos_malloc(strlen(argv[2])+1);
if (ip_addr == NULL) {
k_err_proc(RHINO_NO_MEM);
}
strncpy(ip_addr, argv[2], strlen(argv[2]));
ip_addr[strlen(argv[2])] = '\0';
}
if (argc ==4){
ip_port = atoi(argv[3]);
}
} else {
aos_cli_printf("trace must specify the host ip (port)... \r\n");
return ;
}
if (trace_task == NULL && krhino_task_dyn_create(&trace_task, "trace_task", NULL, 3,
0, TRACE_TASK_STACK_SIZE, trace_entry, 1) != RHINO_SUCCESS) {
aos_cli_printf("trace task creat fail \r\n");
}
} else if (strcmp(rtype, "task") == 0) {
if (argc != 3) {
return;
}
if (filter_task) {
aos_free(filter_task);
}
filter_task = (char *) aos_malloc(strlen(argv[2])+1);
if (filter_task == NULL) {
k_err_proc(RHINO_NO_MEM);
}
strncpy(filter_task, argv[2], strlen(argv[2]));
filter_task[strlen(argv[2])] = '\0';
set_filter_task(filter_task);
} else if (strcmp(rtype, "event") == 0) {
if (argc != 3) {
return;
}
set_event_mask(atoi(argv[2]));
} else if (strcmp(rtype, "stop") == 0) {
trace_is_started = 0;
}
}
static struct cli_command ncmd = {
.name = "trace",
.help = "trace [start ip (port) | task task_name| event event_id| stop]",
.function = handle_trace_cmd,
};
void trace_start(void)
{
aos_cli_register_command(&ncmd);
}
#else
void trace_start(void)
{
printf("trace config close!!!\r\n");
}
#endif /* Trace end*/
#else
void trace_start(void)
{
printf("trace should have cli to control!!!\r\n");
}
#endif /*Cli end*/

View file

@ -0,0 +1,9 @@
#set remotetimeout 20i
target jtag jtag://192.168.254.1:1025
set *0x50006004=0x40000
set *0x4000202c=0xc0206
set *0x40002004=0x8
set $pc =0x10000800
set $psr=0xc0000000

9
Living_SDK/platform/mcu/csky/csi/.gitignore vendored Executable file
View file

@ -0,0 +1,9 @@
!.gitignore
out
include/csi_config.h
.config.old
tools/output/
.config
*.o
*.d
.*.swp

View file

@ -0,0 +1,262 @@
##
# Copyright (C) 2017 C-SKY Microsystems Co., Ltd. All rights reserved.
#
# 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 makefile
# @brief the makefile for the whole project
# @version V1.0
# @date 02. June 2017
###############################################################################
ABSROOTDIR = $(shell pwd)
ROOTDIR = .
TARGETS_ROOT_PATH ?=
CONFIG_FILE ?=
CONFIG_INC_PATH ?=
ifneq ($(CONFIG_FILE),)
CONFIG_FILE_CHECK:= $(shell ls $(CONFIG_FILE) 2>/dev/null)
endif
ifeq ($(CONFIG_FILE_CHECK),)
$(info "CONFIG_FILE not set")
else
include $(CONFIG_FILE)
ifeq ($(CONFIG_CPU_CK610), y)
CC = $(TOOL_PATH)csky-elf-gcc
AS = $(TOOL_PATH)csky-elf-as
AR = $(TOOL_PATH)csky-elf-ar
LD = $(TOOL_PATH)csky-elf-ld
DUMP = $(TOOL_PATH)csky-elf-objdump
OBJCOPY = $(TOOL_PATH)csky-elf-objcopy
else
CC = $(TOOL_PATH)csky-abiv2-elf-gcc
AS = $(TOOL_PATH)csky-abiv2-elf-as
AR = $(TOOL_PATH)csky-abiv2-elf-ar
LD = $(TOOL_PATH)csky-abiv2-elf-ld
DUMP = $(TOOL_PATH)csky-abiv2-elf-objdump
OBJCOPY = $(TOOL_PATH)csky-abiv2-elf-objcopy
endif
CONFIG_CHIP_VENDOR_NAME := $(patsubst "%",%,$(strip $(CONFIG_CHIP_VENDOR_STR)))
CONFIG_CHIP_NAME := $(patsubst "%",%,$(strip $(CONFIG_CHIP_NAME_STR)))
CONFIG_BOARD_NAME := $(patsubst "%",%,$(strip $(CONFIG_BOARD_NAME_STR)))
CONFIG_DEBUG_LEVEL := $(patsubst "%", %, $(strip $(CONFIG_DEBUG_LEVEL)))
CONFIG_OPTIMIZE_LEVEL := $(patsubst "%", %, $(strip $(CONFIG_OPTIMIZE_LEVEL)))
ifeq ($(CONFIG_BIG_ENDIAN),y)
ENDIAN_MODE = -mbig-endian
else
ENDIAN_MODE = -mlittle-endian
endif
OUTDIR = out
OBJDIR = $(OUTDIR)/obj
CSIDRIVERDIR = $(ROOTDIR)/csi_driver
COREDIR = $(ROOTDIR)/csi_core
OFFCHIPDRIVERDIR = $(ROOTDIR)/drivers
DRIVERDIR = $(ROOTDIR)/csi_driver/$(CONFIG_CHIP_VENDOR_NAME)/common
LIBSDIR = $(ROOTDIR)/libs
CHIPDIR = $(ROOTDIR)/csi_driver/$(CONFIG_CHIP_VENDOR_NAME)/$(CONFIG_CHIP_NAME)
KERNELDIR = $(ROOTDIR)/csi_kernel
INCDIR =
CSRC =
LDDIR = $(ROOTDIR)/csi_driver/$(CONFIG_CHIP_VENDOR_NAME)/$(CONFIG_CHIP_NAME)
NAME = $(CONFIG_BOARD_NAME)
PACKNAME = libcsi.a
export CC AS AR LD DUMP OBJCOPY CFLAGS LDFLAGS ASFLAGS INCLUDEDIRS ROOTDIR TARGERDIR DRIVERDIR COREDIR TESTDIR KERNELDIR OFFCHIPDRIVERDIR
$(shell [ -d ${OUTDIR} ] || mkdir -p ${OUTDIR} && mkdir -p ${OBJDIR})
include $(CHIPDIR)/csi.mk
include $(OFFCHIPDRIVERDIR)/csi.mk
include $(LIBSDIR)/csi.mk
ifneq ($(CONFIG_KERNEL_NONE), y)
include $(KERNELDIR)/csi.mk
endif
INCLUDEDIRS = -I$(ROOTDIR)/include -I$(COREDIR)/include -I$(CSIDRIVERDIR)/include -I$(TESTDIR)/include -I$(KERNELDIR)/include -I$(LIBSDIR)/include
INCLUDEDIRS += $(INCDIR)
ifneq ($(TARGETS_ROOT_PATH),)
INCLUDEDIRS += -I$(TARGETS_ROOT_PATH)/include
endif
ifneq ($(CONFIG_INC_PATH),)
INCLUDEDIRS += -I$(CONFIG_INC_PATH)
endif
ifneq ($(BOARD_INCDIR),)
INCLUDEDIRS += -I$(BOARD_INCDIR)
endif
ifeq ($(CONFIG_CPU_CK801), y)
CPU += -mcpu=ck801
endif
ifeq ($(CONFIG_CPU_CK802), y)
CPU += -mcpu=ck802
endif
ifeq ($(CONFIG_CPU_CK803), y)
CPU += -mcpu=ck803sf
endif
ifeq ($(CONFIG_CPU_CK610), y)
ifeq ($(CONFIG_HAS_DSP), y)
CPU += -mcpu=ck610e
endif
endif
CFLAGS += $(CPU) -c -Wa,-melrw
ifeq ($(CONFIG_HARD_FLOAT), y)
CFLAGS += -mhard-float
endif
CFLAGS += $(CONFIG_DEBUG_LEVEL) $(CONFIG_OPTIMIZE_LEVEL) $(CONFIG_ENDIAN_MODE)
CFLAGS += -Wall
CFLAGS += -ffunction-sections
CFLAGS += -fdata-sections
ifeq ($(CONFIG_HAVE_VIC), y)
CFLAGS += -mistack
endif
CFLAGS += $(INCLUDEDIRS)
ifeq ($(CONFIG_BENCHMARK_COREMARK), y)
CFLAGS += -DCOMPILER_FLAGS=\"-Os\"
endif
LDFLAGS = -EL $(CPU)
ASFLAGS = $(CFLAGS)
ARFLAGS = r
LDLIBS = -lm -lc -lgcc -Wl,--gc-section
ifeq ($(V),1)
Q =
else
Q = @
endif
export Q
.PHONY: all
all: lib
lib: lib_sub
S_SRC = $(wildcard $(SSRC))
C_SRC = $(wildcard $(CSRC))
CPP_SRC = $(wildcard $(CPPSRC))
CORE_C_SRC = $(wildcard $(CORE_CSRC))
DRIVER_S_SRC = $(wildcard $(DRIVER_SSRC))
DRIVER_C_SRC = $(wildcard $(DRIVER_CSRC))
KERNEL_S_SRC = $(wildcard $(KERNEL_SSRC))
KERNEL_C_SRC = $(wildcard $(KERNEL_CSRC))
LIB_S_SRC = $(wildcard $(LIB_SSRC))
LIB_C_SRC = $(wildcard $(LIB_CSRC))
CMSIS_S_SRC = $(wildcard $(CMSIS_SSRC))
CMSIS_C_SRC = $(wildcard $(CMSIS_CSRC))
MBEDOS_S_SRC = $(wildcard $(MBEDOS_SSRC))
MBEDOS_C_SRC = $(wildcard $(MBEDOS_CSRC))
MBEDOS_CPP_SRC = $(wildcard $(MBEDOS_CPPSRC))
DOBJECTS = $(C_SRC:%.c=%.o) $(S_SRC:%.S=%.o) $(CPP_SRC:%.cpp=%.o)
CORE_DOBJECTS = $(CORE_C_SRC:%.c=%.o)
DRIVER_DOBJECTS = $(DRIVER_C_SRC:%.c=%.o) $(DRIVER_S_SRC:%.S=%.o)
KERNEL_DOBJECTS = $(KERNEL_C_SRC:%.c=%.o) $(KERNEL_S_SRC:%.S=%.o)
LIB_DOBJECTS = $(LIB_C_SRC:%.c=%.o) $(LIB_S_SRC:%.S=%.o)
CMSIS_DOBJECTS = $(CMSIS_C_SRC:%.c=%.o) $(CMSIS_S_SRC:%.S=%.o)
MBEDOS_DOBJECTS = $(MBEDOS_C_SRC:%.c=%.o) $(MBEDOS_S_SRC:%.S=%.o) $(MBEDOS_CPP_SRC:%.cpp=%.o)
L_DEPS := $(DOBJECTS:%o=%d) $(CORE_DOBJECTS:%o=%d) $(DRIVER_DOBJECTS:%o=%d) $(KERNEL_DOBJECTS:%o=%d) $(LIB_DOBJECTS:%o=%d) \
$(CMSIS_DOBJECTS:%o=%d) $(MBEDOS_DOBJECTS:%o=%d)
lib_sub: $(CORE_DOBJECTS) $(DRIVER_DOBJECTS) $(KERNEL_DOBJECTS) $(LIB_DOBJECTS) $(CMSIS_DOBJECTS) $(MBEDOS_DOBJECTS)
$(Q)$(AR) $(ARFLAGS) $(OUTDIR)/$(PACKNAME) $(CORE_DOBJECTS) $(DRIVER_DOBJECTS) $(KERNEL_DOBJECTS) $(LIB_DOBJECTS)
$(Q)$(AR) $(ARFLAGS) $(OUTDIR)/libcmsis.a $(CMSIS_DOBJECTS)
$(Q)$(AR) $(ARFLAGS) $(OUTDIR)/libmbedos.a $(MBEDOS_DOBJECTS)
main_objs: $(DOBJECTS)
%.o:%.c
@echo CC $<
$(Q)$(CC) -MP -MMD $(CFLAGS) -o $@ $<
%.o:%.S
@echo AS $<
$(Q)$(CC) -MP -MMD $(ASFLAGS) -o $@ $<
%.o:%.cpp
@echo CPP $<
$(Q)$(CPP) -MP -MMD $(CFLAGS) -o $@ $<
sinclude $(L_DEPS)
$(NAME).elf: lib_sub main_objs $(LDDIR)/gcc_csky.ld
@echo LINK $@
$(Q)$(CC) -T $(LDDIR)/gcc_csky.ld -o $(OUTDIR)/$(NAME).elf $(CPPLDFLAG_BEGIN) $(LDFLAGS) \
$(DOBJECTS) $(EOBJECTS) $(CORE_DOBJECTS) $(DRIVER_DOBJECTS) $(KERNEL_DOBJECTS) $(LIB_DOBJECTS) \
$(CMSIS_DOBJECTS) $(MBEDOS_DOBJECTS) \
$(SUBDIR_FILES) $(LDLIBS) $(CPPLDFLAG_END) -nostartfiles
@-cp $(DOBJECTS) $(OBJDIR)
@echo DUMP $@ to $(NAME).asm
$(Q)$(DUMP) -S $(OUTDIR)/$(NAME).elf > $(OUTDIR)/$(NAME).asm
@echo OBJCOPY $@ to $(NAME).bin
$(Q)$(OBJCOPY) -O binary $(OUTDIR)/$(NAME).elf $(OUTDIR)/$(NAME).bin
$(Q)$(OBJCOPY) -O srec $(OUTDIR)/$(NAME).elf $(OUTDIR)/$(NAME).hex
.PHONY : debug-make
DEBUG_VARS = SUB_DIRS \
SUBDIR_FILES\
INCLUDEDIRS \
CSRC \
SSRC \
EOBJECTS \
DOBJECTS \
ASFLAGS \
CFLAGS
#:
#: debug-make -- Print a list of Makefile variables
debug-make:
@$(foreach var, $(DEBUG_VARS), echo $(var)=$($(var)) ; )
test_core:
sh ./products/unit_test/core_test/testsuite/core_test.sh
endif
###############
clean:
rm -rf $(OUTDIR)
# rm -f $(DOBJECTS)
# rm -f $(L_DEPS)
find . -name "*.d" | xargs rm -f
find . -name "*.o" | xargs rm -f
rm out -fr
# rm -f include/csi_config.h
tee_os:
@make -C $(ROOTDIR)/csi_driver/$(CONFIG_CHIP_VENDOR_STR)/common/tee \
TEEOS_LIB_PATH=$(ABSROOTDIR)/$(CHIPDIR)/tee/ \
TEEOS_LIB=libtee_os_$(CONFIG_CHIP_NAME_STR).a \
TARGETS_ROOT_PATH=$(TARGETS_ROOT_PATH)

View file

@ -0,0 +1 @@
v1.3

View file

@ -0,0 +1 @@
Just include csi_core.h!

View file

@ -0,0 +1,539 @@
/*
* Copyright (C) 2017 C-SKY Microsystems Co., Ltd. All rights reserved.
*
* 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 core_ck610.h
* @brief CSI CK610 Core Peripheral Access Layer Header File
* @version V1.0
* @date 02. June 2017
******************************************************************************/
#ifndef __CORE_CK610_H_GENERIC
#define __CORE_CK610_H_GENERIC
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
/*******************************************************************************
* CSI definitions
******************************************************************************/
/**
\ingroup Ck610
@{
*/
/* CSI CK610 definitions */
#define __CK610_CSI_VERSION_MAIN (0x01U) /*!< [31:16] CSI HAL main version */
#define __CK610_CSI_VERSION_SUB (0x1EU) /*!< [15:0] CSI HAL sub version */
#define __CK610_CSI_VERSION ((__CK610_CSI_VERSION_MAIN << 16U) | \
__CK610_CSI_VERSION_SUB ) /*!< CSI HAL version number */
#define __CK610 (0x01U) /*!< CK610 Core */
/** __FPU_USED indicates whether an FPU is used or not.
This core does not support an FPU at all
*/
#define __FPU_USED 0U
#if defined ( __GNUC__ )
#if defined (__VFP_FP__) && !defined(__SOFTFP__)
#error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
#endif
#endif
#ifdef __cplusplus
}
#endif
#endif /* __CORE_CK610_H_GENERIC */
#ifndef __CSI_GENERIC
#ifndef __CORE_CK610_H_DEPENDANT
#define __CORE_CK610_H_DEPENDANT
#ifdef __cplusplus
extern "C" {
#endif
/* check device defines and use defaults */
//#if defined __CHECK_DEVICE_DEFINES
#ifndef __CK610_REV
#define __CK610_REV 0x0000U
//#warning "__CK610_REV not defined in device header file; using default!"
#endif
#ifndef __VIC_PRIO_BITS
#define __VIC_PRIO_BITS 2U
//#warning "__VIC_PRIO_BITS not defined in device header file; using default!"
#endif
#ifndef __Vendor_SysTickConfig
#define __Vendor_SysTickConfig 0U
//#warning "__Vendor_SysTickConfig not defined in device header file; using default!"
#endif
#ifndef __GSR_GCR_PRESENT
#define __GSR_GCR_PRESENT 0U
//#warning "__GSR_GCR_PRESENT not defined in device header file; using default!"
#endif
#ifndef __MGU_PRESENT
#define __MGU_PRESENT 0U
//#warning "__MGU_PRESENT not defined in device header file; using default!"
#endif
#ifndef __ICACHE_PRESENT
#define __ICACHE_PRESENT 0U
//#warning "__ICACHE_PRESENT not defined in device header file; using default!"
#endif
#ifndef __DCACHE_PRESENT
#define __DCACHE_PRESENT 0U
//#warning "__DCACHE_PRESENT not defined in device header file; using default!"
#endif
#include <csi_gcc.h>
//#endif
/* IO definitions (access restrictions to peripheral registers) */
/**
\defgroup CSI_glob_defs CSI Global Defines
<strong>IO Type Qualifiers</strong> are used
\li to specify the access to peripheral variables.
\li for automatic generation of peripheral register debug information.
*/
#ifdef __cplusplus
#define __I volatile /*!< Defines 'read only' permissions */
#else
#define __I volatile const /*!< Defines 'read only' permissions */
#endif
#define __O volatile /*!< Defines 'write only' permissions */
#define __IO volatile /*!< Defines 'read / write' permissions */
/* following defines should be used for structure members */
#define __IM volatile const /*! Defines 'read only' structure member permissions */
#define __OM volatile /*! Defines 'write only' structure member permissions */
#define __IOM volatile /*! Defines 'read / write' structure member permissions */
/*@} end of group CK610 */
/*******************************************************************************
* Register Abstraction
Core Register contain:
- Core Register
- Core VIC Register
- Core SCB Register
- Core SysTick Register
******************************************************************************/
/**
\defgroup CSI_core_register Defines and Type Definitions
\brief Type definitions and defines for CK610 processor based devices.
*/
/**
\brief Consortium definition for accessing Cache Configuration Registers(CCR, CR<18, 0>).
*/
typedef union {
struct {
uint32_t MP: 1; /*!< bit: 0 memory protection settings */
uint32_t _reserved0: 6; /*!< bit: 1.. 6 Reserved */
uint32_t BE: 1; /*!< bit: 7 Endian mode */
uint32_t SCK: 3; /*!< bit: 8..10 the clock ratio of the system and the processor */
uint32_t _reserved1: 2; /*!< bit: 11..12 Reserved */
uint32_t BE_V2: 1; /*!< bit: 13 V2 Endian mode */
uint32_t _reserved2: 18; /*!< bit: 14..31 Reserved */
} b; /*!< Structure Access by bit */
uint32_t w; /*!< Type Access by whole register */
} CCR_Type;
/* CCR Register Definitions */
#define CCR_BE_V2_Pos 13U /*!< CCR: BE_V2 Position */
#define CCR_BE_V2_Msk (0x1UL << CCR_BE_V2_Pos) /*!< CCR: BE_V2 Mask */
#define CCR_SCK_Pos 8U /*!< CCR: SCK Position */
#define CCR_SCK_Msk (0x3UL << CCR_SCK_Pos) /*!< CCR: SCK Mask */
#define CCR_BE_Pos 7U /*!< CCR: BE Position */
#define CCR_BE_Msk (0x1UL << CCR_BE_Pos) /*!< CCR: BE Mask */
#define CCR_MP_Pos 0U /*!< CCR: MP Position */
#define CCR_MP_Msk (0x1UL << CCR_MP_Pos) /*!< CCR: MP Mask */
/**
\brief Consortium definition for accessing high ease access permission configutation registers(CAPR, CR<19,0>).
*/
typedef union {
struct {
//TODO:
} b; /*!< Structure Access by bit */
uint32_t w; /*!< Type Access by whole register */
} CAPR_Type;
/* CAPR Register Definitions */
#define CAPR_S7_Pos 31U /*!< CAPR: S7 Position */
#define CAPR_S7_Msk (1UL << CAPR_S7_Pos) /*!< CAPR: S7 Mask */
#define CAPR_S6_Pos 30U /*!< CAPR: S6 Position */
#define CAPR_S6_Msk (1UL << CAPR_S6_Pos) /*!< CAPR: S6 Mask */
#define CAPR_S5_Pos 29U /*!< CAPR: S5 Position */
#define CAPR_S5_Msk (1UL << CAPR_S5_Pos) /*!< CAPR: S5 Mask */
#define CAPR_S4_Pos 28U /*!< CAPR: S4 Position */
#define CAPR_S4_Msk (1UL << CAPR_S4_Pos) /*!< CAPR: S4 Mask */
#define CAPR_S3_Pos 27U /*!< CAPR: S3 Position */
#define CAPR_S3_Msk (1UL << CAPR_S3_Pos) /*!< CAPR: S3 Mask */
#define CAPR_S2_Pos 26U /*!< CAPR: S2 Position */
#define CAPR_S2_Msk (1UL << CAPR_S2_Pos) /*!< CAPR: S2 Mask */
#define CAPR_S1_Pos 25U /*!< CAPR: S1 Position */
#define CAPR_S1_Msk (1UL << CAPR_S1_Pos) /*!< CAPR: S1 Mask */
#define CAPR_S0_Pos 24U /*!< CAPR: S0 Position */
#define CAPR_S0_Msk (1UL << CAPR_S0_Pos) /*!< CAPR: S0 Mask */
#define CAPR_AP7_Pos 22U /*!< CAPR: AP7 Position */
#define CAPR_AP7_Msk (0x3UL << CAPR_AP7_Pos) /*!< CAPR: AP7 Mask */
#define CAPR_AP6_Pos 20U /*!< CAPR: AP6 Position */
#define CAPR_AP6_Msk (0x3UL << CAPR_AP6_Pos) /*!< CAPR: AP6 Mask */
#define CAPR_AP5_Pos 18U /*!< CAPR: AP5 Position */
#define CAPR_AP5_Msk (0x3UL << CAPR_AP5_Pos) /*!< CAPR: AP5 Mask */
#define CAPR_AP4_Pos 16U /*!< CAPR: AP4 Position */
#define CAPR_AP4_Msk (0x3UL << CAPR_AP4_Pos) /*!< CAPR: AP4 Mask */
#define CAPR_AP3_Pos 14U /*!< CAPR: AP3 Position */
#define CAPR_AP3_Msk (0x3UL << CAPR_AP3_Pos) /*!< CAPR: AP3 Mask */
#define CAPR_AP2_Pos 12U /*!< CAPR: AP2 Position */
#define CAPR_AP2_Msk (0x3UL << CAPR_AP2_Pos) /*!< CAPR: AP2 Mask */
#define CAPR_AP1_Pos 10U /*!< CAPR: AP1 Position */
#define CAPR_AP1_Msk (0x3UL << CAPR_AP1_Pos) /*!< CAPR: AP1 Mask */
#define CAPR_AP0_Pos 8U /*!< CAPR: AP0 Position */
#define CAPR_AP0_Msk (0x3UL << CAPR_AP0_Pos) /*!< CAPR: AP0 Mask */
#define CAPR_X7_Pos 7U /*!< CAPR: X7 Position */
#define CAPR_X7_Msk (0x1UL << CAPR_X7_Pos) /*!< CAPR: X7 Mask */
#define CAPR_X6_Pos 6U /*!< CAPR: X6 Position */
#define CAPR_X6_Msk (0x1UL << CAPR_X6_Pos) /*!< CAPR: X6 Mask */
#define CAPR_X5_Pos 5U /*!< CAPR: X5 Position */
#define CAPR_X5_Msk (0x1UL << CAPR_X5_Pos) /*!< CAPR: X5 Mask */
#define CAPR_X4_Pos 4U /*!< CAPR: X4 Position */
#define CAPR_X4_Msk (0x1UL << CAPR_X4_Pos) /*!< CAPR: X4 Mask */
#define CAPR_X3_Pos 3U /*!< CAPR: X3 Position */
#define CAPR_X3_Msk (0x1UL << CAPR_X3_Pos) /*!< CAPR: X3 Mask */
#define CAPR_X2_Pos 2U /*!< CAPR: X2 Position */
#define CAPR_X2_Msk (0x1UL << CAPR_X2_Pos) /*!< CAPR: X2 Mask */
#define CAPR_X1_Pos 1U /*!< CAPR: X1 Position */
#define CAPR_X1_Msk (0x1UL << CAPR_X1_Pos) /*!< CAPR: X1 Mask */
#define CAPR_X0_Pos 0U /*!< CAPR: X0 Position */
#define CAPR_X0_Msk (0x1UL << CAPR_X0_Pos) /*!< CAPR: X0 Mask */
/**
\brief Consortium definition for accessing control register(PACR, CR<20,0>).
*/
typedef union {
struct {
uint32_t E: 1; /*!< bit: 0 Effective setting of protected area */
uint32_t Size: 5; /*!< bit: 1.. 5 Size of protected area */
uint32_t _reserved0: 4; /*!< bit: 6.. 9 Reserved */
uint32_t base_addr: 22; /*!< bit: 10..31 The high position of the address of a protected area */
} b; /*!< Structure Access by bit */
uint32_t w; /*!< Type Access by whole register */
} PACR_Type;
/* PACR Register Definitions */
#define PACR_BASE_ADDR_Pos 10U /*!< PACR: base_addr Position */
#define PACK_BASE_ADDR_Msk (0x3FFFFFUL << PACR_BASE_ADDR_Pos) /*!< PACR: base_addr Mask */
#define PACR_SIZE_Pos 1U /*!< PACR: Size Position */
#define PACK_SIZE_Msk (0x1FUL << PACR_SIZE_Pos) /*!< PACR: Size Mask */
#define PACR_E_Pos 0U /*!< PACR: E Position */
#define PACK_E_Msk (0x1UL << PACR_E_Pos) /*!< PACR: E Mask */
/**
\brief Consortium definition for accessing protection area selection register(PRSR,CR<21,0>).
*/
typedef union {
struct {
uint32_t RID: 3; /*!< bit: 0.. 2 Protected area index value */
uint32_t _reserved0: 29; /*!< bit: 3..31 Reserved */
} b; /*!< Structure Access by bit */
uint32_t w; /*!< Type Access by whole register */
} PRSR_Type;
/* PRSR Register Definitions */
#define PRSR_RID_Pos 0U /*!< PRSR: RID Position */
#define PRSR_RID_Msk (0x7UL << PRSR_RID_Pos) /*!< PRSR: RID Mask */
/*@} end of group CSI_CORE */
/**
\ingroup CSI_core_register
\defgroup CSI_CACHE
\brief Type definitions for the cache Registers
@{
*/
#define set_cr17(value) \
__asm__ __volatile__( \
"mtcr %0, cr17\n\t" \
::"r"(value))
#define set_cr22(value) \
__asm__ __volatile__("mtcr %0, cr22\n\t" \
::"r"(value))
#define SSEG0_BASE_ADDR 0x80000000
#define CACHE_RANGE_MAX_SIZE 0x80000
#define INS_CACHE (1 << 0)
#define DATA_CACHE (1 << 1)
#define CACHE_INV (1 << 4)
#define CACHE_CLR (1 << 5)
#define CACHE_OMS (1 << 6)
#define CACHE_ITS (1 << 7)
#define CACHE_LICF (1 << 31)
#define L1_CACHE_SHIFT 4 /* 16 Bytes */
#define L1_CACHE_BYTES (1 << L1_CACHE_SHIFT)
/**
\brief Mask and shift a bit field value for use in a register bit range.
\param[in] field Name of the register bit field.
\param[in] value Value of the bit field.
\return Masked and shifted value.
*/
#define _VAL2FLD(field, value) ((value << field ## _Pos) & field ## _Msk)
/**
\brief Mask and shift a register value to extract a bit filed value.
\param[in] field Name of the register bit field.
\param[in] value Value of register.
\return Masked and shifted bit field value.
*/
#define _FLD2VAL(field, value) ((value & field ## _Msk) >> field ## _Pos)
/*@} end of group CSI_core_bitfield */
/*******************************************************************************
* Hardware Abstraction Layer
Core Function Interface contains:
- Core VIC Functions
- Core CORET Functions
- Core Register Access Functions
******************************************************************************/
/* ########################## Cache functions #################################### */
/**
\ingroup CSI_Core_FunctionInterface
\defgroup CSI_Core_CacheFunctions Cache Functions
\brief Functions that configure Instruction and Data cache.
@{
*/
/**
\brief Enable I-Cache
\details Turns on I-Cache
*/
__ALWAYS_INLINE void csi_icache_enable (void)
{
uint32_t tmp=0;
__ASM volatile("mfcr %0, cr18\n\t"
"bseti %0, 2\n\t"
"mtcr %0, cr18\n\t"
::"r"(tmp));
}
/**
\brief Disable I-Cache
\details Turns off I-Cache
*/
__ALWAYS_INLINE void csi_icache_disable (void)
{
uint32_t tmp=0;
__ASM volatile("mfcr %0, cr18\n\t"
"bclri %0, 2\n\t"
"mtcr %0, cr18\n\t"
::"r"(tmp));
}
/**
\brief Invalidate I-Cache
\details Invalidates I-Cache
*/
__ALWAYS_INLINE void csi_icache_invalid (void)
{
set_cr17(0x11);
set_cr17(INS_CACHE | CACHE_INV);
}
/**
\brief Enable D-Cache
\details Turns on D-Cache
\note I-Cache also turns on.
*/
__ALWAYS_INLINE void csi_dcache_enable (void)
{
uint32_t tmp=0;
__ASM volatile("mfcr %0, cr18\n\t"
"bseti %0, 3\n\t"
"mtcr %0, cr18\n\t"
::"r"(tmp));
}
/**
\brief Disable D-Cache
\details Turns off D-Cache
\note I-Cache also turns off.
*/
__ALWAYS_INLINE void csi_dcache_disable (void)
{
uint32_t tmp=0;
__ASM volatile("mfcr %0, cr18\n\t"
"bclri %0, 3\n\t"
"mtcr %0, cr18\n\t"
::"r"(tmp));
}
/**
\brief Invalidate D-Cache
\details Invalidates D-Cache
\note I-Cache also invalid
*/
__ALWAYS_INLINE void csi_dcache_invalid (void)
{
set_cr17(DATA_CACHE | CACHE_INV);
}
/**
\brief Clean D-Cache
\details Cleans D-Cache
\note I-Cache also cleans
*/
__ALWAYS_INLINE void csi_dcache_clean (void)
{
set_cr17(DATA_CACHE | CACHE_CLR);
}
/**
\brief Clean & Invalidate D-Cache
\details Cleans and Invalidates D-Cache
\note I-Cache also flush.
*/
__ALWAYS_INLINE void csi_dcache_clean_invalid (void)
{
set_cr17(DATA_CACHE | CACHE_CLR | CACHE_INV);
}
__ALWAYS_INLINE void set_cache_range (uint32_t start, uint32_t end, uint32_t value)
{
if (!(start & SSEG0_BASE_ADDR) || (end - start) &~(CACHE_RANGE_MAX_SIZE - 1)) {
set_cr17(value);
}
if (value & INS_CACHE) {
csi_icache_disable();
}
uint32_t i;
for (i = start; i < end; i += L1_CACHE_BYTES) {
set_cr22(i);
set_cr17(CACHE_OMS | value);
}
if (end & (L1_CACHE_BYTES-1)) {
set_cr22(end);
set_cr17(CACHE_OMS | value);
}
if (value & INS_CACHE) {
csi_icache_enable();
}
}
/**
\brief D-Cache Invalidate by address
\details Invalidates D-Cache for the given address
\param[in] addr address (aligned to 16-byte boundary)
\param[in] dsize size of memory block (in number of bytes)
*/
__ALWAYS_INLINE csi_dcache_invalid_range (uint32_t *addr, int32_t dsize)
{
set_cache_range((uint32_t)addr, (uint32_t)addr + dsize, (DATA_CACHE | CACHE_INV));
}
/**
\brief D-Cache Clean by address
\details Cleans D-Cache for the given address
\param[in] addr address (aligned to 16-byte boundary)
\param[in] dsize size of memory block (in number of bytes)
*/
__ALWAYS_INLINE void csi_dcache_clean_range (uint32_t *addr, int32_t dsize)
{
set_cache_range((uint32_t)addr, (uint32_t)addr + dsize, (DATA_CACHE | CACHE_CLR));
}
/**
\brief D-Cache Clean and Invalidate by address
\details Cleans and invalidates D_Cache for the given address
\param[in] addr address (aligned to 16-byte boundary)
\param[in] dsize size of memory block (in number of bytes)
*/
__ALWAYS_INLINE void csi_dcache_clean_invalid_range (uint32_t *addr, int32_t dsize)
{
set_cache_range((uint32_t)addr, (uint32_t)addr + dsize, (DATA_CACHE | CACHE_CLR | CACHE_INV));
}
/*@} end of CSI_Core_CacheFunctions */
/*@} */
#ifdef __cplusplus
}
#endif
#endif /* __CORE_CK610_H_DEPENDANT */
#endif /* __CSI_GENERIC */

View file

@ -0,0 +1,935 @@
/*
* Copyright (C) 2017 C-SKY Microsystems Co., Ltd. All rights reserved.
*
* 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 core_ck801.h
* @brief CSI CK801 Core Peripheral Access Layer Header File
* @version V1.0
* @date 02. June 2017
******************************************************************************/
#ifndef __CORE_CK801_H_GENERIC
#define __CORE_CK801_H_GENERIC
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
/*******************************************************************************
* CSI definitions
******************************************************************************/
/**
\ingroup Ck801
@{
*/
/* CSI CK801 definitions */
#define __CK801_CSI_VERSION_MAIN (0x04U) /*!< [31:16] CSI HAL main version */
#define __CK801_CSI_VERSION_SUB (0x1EU) /*!< [15:0] CSI HAL sub version */
#define __CK801_CSI_VERSION ((__CK801_CSI_VERSION_MAIN << 16U) | \
__CK801_CSI_VERSION_SUB ) /*!< CSI HAL version number */
#ifndef __CK80X
#define __CK80X (0x01U) /*!< CK80X Core */
#endif
/** __FPU_USED indicates whether an FPU is used or not.
This core does not support an FPU at all
*/
#define __FPU_USED 0U
#if defined ( __GNUC__ )
#if defined (__VFP_FP__) && !defined(__SOFTFP__)
#error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
#endif
#endif
#ifdef __cplusplus
}
#endif
#endif /* __CORE_CK801_H_GENERIC */
#ifndef __CSI_GENERIC
#ifndef __CORE_CK801_H_DEPENDANT
#define __CORE_CK801_H_DEPENDANT
#ifdef __cplusplus
extern "C" {
#endif
/* check device defines and use defaults */
//#if defined __CHECK_DEVICE_DEFINES
#ifndef __CK801_REV
#define __CK801_REV 0x0000U
//#warning "__CK801_REV not defined in device header file; using default!"
#endif
#ifndef __VIC_PRIO_BITS
#define __VIC_PRIO_BITS 2U
//#warning "__VIC_PRIO_BITS not defined in device header file; using default!"
#endif
#ifndef __Vendor_SysTickConfig
#define __Vendor_SysTickConfig 1U
//#warning "__Vendor_SysTickConfig not defined in device header file; using default!"
#endif
#ifndef __GSR_GCR_PRESENT
#define __GSR_GCR_PRESENT 0U
//#warning "__GSR_GCR_PRESENT not defined in device header file; using default!"
#endif
#ifndef __MPU_PRESENT
#define __MPU_PRESENT 1U
//#warning "__MPU_PRESENT not defined in device header file; using default!"
#endif
//#endif
#include <csi_gcc.h>
/* IO definitions (access restrictions to peripheral registers) */
/**
\defgroup CSI_glob_defs CSI Global Defines
<strong>IO Type Qualifiers</strong> are used
\li to specify the access to peripheral variables.
\li for automatic generation of peripheral register debug information.
*/
#ifdef __cplusplus
#define __I volatile /*!< Defines 'read only' permissions */
#else
#define __I volatile const /*!< Defines 'read only' permissions */
#endif
#define __O volatile /*!< Defines 'write only' permissions */
#define __IO volatile /*!< Defines 'read / write' permissions */
/* following defines should be used for structure members */
#define __IM volatile const /*! Defines 'read only' structure member permissions */
#define __OM volatile /*! Defines 'write only' structure member permissions */
#define __IOM volatile /*! Defines 'read / write' structure member permissions */
/*@} end of group CK801 */
/*******************************************************************************
* Register Abstraction
Core Register contain:
- Core Register
- Core VIC Register
- Core SCB Register
- Core SysTick Register
******************************************************************************/
/**
\defgroup CSI_core_register Defines and Type Definitions
\brief Type definitions and defines for CK80X processor based devices.
*/
/**
\ingroup CSI_core_register
\defgroup CSI_CORE Status and Control Registers
\brief Core Register type definitions.
@{
*/
/**
\brief Access Processor Status Register(PSR)struct definition.
*/
typedef union {
struct {
uint32_t C: 1; /*!< bit: 0 Conditional code/Carry flag */
uint32_t _reserved0: 5; /*!< bit: 2.. 5 Reserved */
uint32_t IE: 1; /*!< bit: 6 Interrupt effective control bit */
uint32_t IC: 1; /*!< bit: 7 Interrupt control bit */
uint32_t EE: 1; /*!< bit: 8 Abnormally effective control bit */
uint32_t MM: 1; /*!< bit: 9 Unsymmetrical masking bit */
uint32_t _reserved1: 6; /*!< bit: 10..15 Reserved */
uint32_t VEC: 8; /*!< bit: 16..23 Abnormal event vector value */
uint32_t _reserved2: 7; /*!< bit: 24..30 Reserved */
uint32_t S: 1; /*!< bit: 31 Superuser mode set bit */
} b; /*!< Structure Access by bit */
uint32_t w; /*!< Type Access by whole register */
} PSR_Type;
/* PSR Register Definitions */
#define PSR_S_Pos 31U /*!< PSR: S Position */
#define PSR_S_Msk (1UL << PSR_S_Pos) /*!< PSR: S Mask */
#define PSR_VEC_Pos 16U /*!< PSR: VEC Position */
#define PSR_VEC_Msk (0x7FUL << PSR_VEC_Pos) /*!< PSR: VEC Mask */
#define PSR_MM_Pos 9U /*!< PSR: MM Position */
#define PSR_MM_Msk (1UL << PSR_MM_Pos) /*!< PSR: MM Mask */
#define PSR_EE_Pos 8U /*!< PSR: EE Position */
#define PSR_EE_Msk (1UL << PSR_EE_Pos) /*!< PSR: EE Mask */
#define PSR_IC_Pos 7U /*!< PSR: IC Position */
#define PSR_IC_Msk (1UL << PSR_IC_Pos) /*!< PSR: IC Mask */
#define PSR_IE_Pos 6U /*!< PSR: IE Position */
#define PSR_IE_Msk (1UL << PSR_IE_Pos) /*!< PSR: IE Mask */
#define PSR_C_Pos 0U /*!< PSR: C Position */
#define PSR_C_Msk (1UL << PSR_C_Pos) /*!< PSR: C Mask */
/**
\brief Consortium definition for accessing Cache Configuration Registers(CCR, CR<18, 0>).
*/
typedef union {
struct {
uint32_t MP: 1; /*!< bit: 0 memory protection settings */
uint32_t _reserved0: 6; /*!< bit: 1.. 6 Reserved */
uint32_t BE: 1; /*!< bit: 7 Endian mode */
uint32_t SCK: 3; /*!< bit: 8..10 the clock ratio of the system and the processor */
uint32_t _reserved1: 2; /*!< bit: 11..12 Reserved */
uint32_t BE_V2: 1; /*!< bit: 13 V2 Endian mode */
uint32_t _reserved2: 18; /*!< bit: 14..31 Reserved */
} b; /*!< Structure Access by bit */
uint32_t w; /*!< Type Access by whole register */
} CCR_Type;
/* CCR Register Definitions */
#define CCR_BE_V2_Pos 13U /*!< CCR: BE_V2 Position */
#define CCR_BE_V2_Msk (0x1UL << CCR_ISR_Pos) /*!< CCR: BE_V2 Mask */
#define CCR_SCK_Pos 8U /*!< CCR: SCK Position */
#define CCR_SCK_Msk (0x3UL << CCR_SCK_Pos) /*!< CCR: SCK Mask */
#define CCR_BE_Pos 7U /*!< CCR: BE Position */
#define CCR_BE_Msk (0x1UL << CCR_BE_Pos) /*!< CCR: BE Mask */
#define CCR_MP_Pos 0U /*!< CCR: MP Position */
#define CCR_MP_Msk (0x1UL << CCR_MP_Pos) /*!< CCR: MP Mask */
/**
\brief Consortium definition for accessing high ease access permission configutation registers(CAPR, CR<19,0>)
*/
typedef union {
struct {
uint32_t X0: 1; /*!< bit: 0 Non executable attribute setting */
uint32_t X1: 1; /*!< bit: 1 Non executable attribute setting */
uint32_t X2: 1; /*!< bit: 2 Non executable attribute setting */
uint32_t X3: 1; /*!< bit: 3 Non executable attribute setting */
uint32_t X4: 1; /*!< bit: 4 Non executable attribute setting */
uint32_t X5: 1; /*!< bit: 5 Non executable attribute setting */
uint32_t X6: 1; /*!< bit: 6 Non executable attribute setting */
uint32_t X7: 1; /*!< bit: 7 Non executable attribute setting */
uint32_t AP0: 2; /*!< bit: 8.. 9 access permissions settings bit */
uint32_t AP1: 2; /*!< bit: 10..11 access permissions settings bit */
uint32_t AP2: 2; /*!< bit: 12..13 access permissions settings bit */
uint32_t AP3: 2; /*!< bit: 14..15 access permissions settings bit */
uint32_t AP4: 2; /*!< bit: 16..17 access permissions settings bit */
uint32_t AP5: 2; /*!< bit: 18..19 access permissions settings bit */
uint32_t AP6: 2; /*!< bit: 20..21 access permissions settings bit */
uint32_t AP7: 2; /*!< bit: 22..23 access permissions settings bit */
uint32_t S0: 1; /*!< bit: 24 Security property settings */
uint32_t S1: 1; /*!< bit: 25 Security property settings */
uint32_t S2: 1; /*!< bit: 26 Security property settings */
uint32_t S3: 1; /*!< bit: 27 Security property settings */
uint32_t S4: 1; /*!< bit: 28 Security property settings */
uint32_t S5: 1; /*!< bit: 29 Security property settings */
uint32_t S6: 1; /*!< bit: 30 Security property settings */
uint32_t S7: 1; /*!< bit: 31 Security property settings */
} b; /*!< Structure Access by bit */
uint32_t w; /*!< Type Access by whole register */
} CAPR_Type;
/* CAPR Register Definitions */
#define CAPR_S7_Pos 31U /*!< CAPR: S7 Position */
#define CAPR_S7_Msk (1UL << CAPR_S7_Pos) /*!< CAPR: S7 Mask */
#define CAPR_S6_Pos 30U /*!< CAPR: S6 Position */
#define CAPR_S6_Msk (1UL << CAPR_S6_Pos) /*!< CAPR: S6 Mask */
#define CAPR_S5_Pos 29U /*!< CAPR: S5 Position */
#define CAPR_S5_Msk (1UL << CAPR_S5_Pos) /*!< CAPR: S5 Mask */
#define CAPR_S4_Pos 28U /*!< CAPR: S4 Position */
#define CAPR_S4_Msk (1UL << CAPR_S4_Pos) /*!< CAPR: S4 Mask */
#define CAPR_S3_Pos 27U /*!< CAPR: S3 Position */
#define CAPR_S3_Msk (1UL << CAPR_S3_Pos) /*!< CAPR: S3 Mask */
#define CAPR_S2_Pos 26U /*!< CAPR: S2 Position */
#define CAPR_S2_Msk (1UL << CAPR_S2_Pos) /*!< CAPR: S2 Mask */
#define CAPR_S1_Pos 25U /*!< CAPR: S1 Position */
#define CAPR_S1_Msk (1UL << CAPR_S1_Pos) /*!< CAPR: S1 Mask */
#define CAPR_S0_Pos 24U /*!< CAPR: S0 Position */
#define CAPR_S0_Msk (1UL << CAPR_S0_Pos) /*!< CAPR: S0 Mask */
#define CAPR_AP7_Pos 22U /*!< CAPR: AP7 Position */
#define CAPR_AP7_Msk (0x3UL << CAPR_AP7_Pos) /*!< CAPR: AP7 Mask */
#define CAPR_AP6_Pos 20U /*!< CAPR: AP6 Position */
#define CAPR_AP6_Msk (0x3UL << CAPR_AP6_Pos) /*!< CAPR: AP6 Mask */
#define CAPR_AP5_Pos 18U /*!< CAPR: AP5 Position */
#define CAPR_AP5_Msk (0x3UL << CAPR_AP5_Pos) /*!< CAPR: AP5 Mask */
#define CAPR_AP4_Pos 16U /*!< CAPR: AP4 Position */
#define CAPR_AP4_Msk (0x3UL << CAPR_AP4_Pos) /*!< CAPR: AP4 Mask */
#define CAPR_AP3_Pos 14U /*!< CAPR: AP3 Position */
#define CAPR_AP3_Msk (0x3UL << CAPR_AP3_Pos) /*!< CAPR: AP3 Mask */
#define CAPR_AP2_Pos 12U /*!< CAPR: AP2 Position */
#define CAPR_AP2_Msk (0x3UL << CAPR_AP2_Pos) /*!< CAPR: AP2 Mask */
#define CAPR_AP1_Pos 10U /*!< CAPR: AP1 Position */
#define CAPR_AP1_Msk (0x3UL << CAPR_AP1_Pos) /*!< CAPR: AP1 Mask */
#define CAPR_AP0_Pos 8U /*!< CAPR: AP0 Position */
#define CAPR_AP0_Msk (0x3UL << CAPR_AP0_Pos) /*!< CAPR: AP0 Mask */
#define CAPR_X7_Pos 7U /*!< CAPR: X7 Position */
#define CAPR_X7_Msk (0x1UL << CAPR_X7_Pos) /*!< CAPR: X7 Mask */
#define CAPR_X6_Pos 6U /*!< CAPR: X6 Position */
#define CAPR_X6_Msk (0x1UL << CAPR_X6_Pos) /*!< CAPR: X6 Mask */
#define CAPR_X5_Pos 5U /*!< CAPR: X5 Position */
#define CAPR_X5_Msk (0x1UL << CAPR_X5_Pos) /*!< CAPR: X5 Mask */
#define CAPR_X4_Pos 4U /*!< CAPR: X4 Position */
#define CAPR_X4_Msk (0x1UL << CAPR_X4_Pos) /*!< CAPR: X4 Mask */
#define CAPR_X3_Pos 3U /*!< CAPR: X3 Position */
#define CAPR_X3_Msk (0x1UL << CAPR_X3_Pos) /*!< CAPR: X3 Mask */
#define CAPR_X2_Pos 2U /*!< CAPR: X2 Position */
#define CAPR_X2_Msk (0x1UL << CAPR_X2_Pos) /*!< CAPR: X2 Mask */
#define CAPR_X1_Pos 1U /*!< CAPR: X1 Position */
#define CAPR_X1_Msk (0x1UL << CAPR_X1_Pos) /*!< CAPR: X1 Mask */
#define CAPR_X0_Pos 0U /*!< CAPR: X0 Position */
#define CAPR_X0_Msk (0x1UL << CAPR_X0_Pos) /*!< CAPR: X0 Mask */
/**
\brief Consortium definition for accessing control register(PACR, CR<20,0>).
*/
typedef union {
struct {
uint32_t E: 1; /*!< bit: 0 Effective setting of protected area */
uint32_t Size: 5; /*!< bit: 1.. 5 Size of protected area */
uint32_t _reserved0: 4; /*!< bit: 6.. 9 Reserved */
uint32_t base_addr: 22; /*!< bit: 10..31 The high position of the address of a protected area */
} b; /*!< Structure Access by bit */
uint32_t w; /*!< Type Access by whole register */
} PACR_Type;
/* PACR Register Definitions */
#define PACR_BASE_ADDR_Pos 10U /*!< PACR: base_addr Position */
#define PACK_BASE_ADDR_Msk (0x3FFFFFUL << PACR_BASE_ADDR_Pos) /*!< PACR: base_addr Mask */
#define PACR_SIZE_Pos 1U /*!< PACR: Size Position */
#define PACK_SIZE_Msk (0x1FUL << PACR_SIZE_Pos) /*!< PACR: Size Mask */
#define PACR_E_Pos 0U /*!< PACR: E Position */
#define PACK_E_Msk (0x1UL << PACR_E_Pos) /*!< PACR: E Mask */
/**
\brief Consortium definition for accessing protection area selection register(PRSR,CR<21,0>).
*/
typedef union {
struct {
uint32_t RID: 3; /*!< bit: 0.. 2 Protected area index value */
uint32_t _reserved0: 29; /*!< bit: 3..31 Reserved */
} b; /*!< Structure Access by bit */
uint32_t w; /*!< Type Access by whole register */
} PRSR_Type;
/* PRSR Register Definitions */
#define PRSR_RID_Pos 0U /*!< PRSR: RID Position */
#define PRSR_RID_Msk (0x7UL << PRSR_RID_Pos) /*!< PRSR: RID Mask */
/*@} end of group CSI_CORE */
/**
\ingroup CSI_core_register
\defgroup CSI_VIC Vectored Interrupt Controller (VIC)
\brief Type definitions for the VIC Registers
@{
*/
/**
\brief Access to the structure of a vector interrupt controller.
*/
typedef struct {
__IOM uint32_t ISER[1U]; /*!< Offset: 0x000 (R/W) Interrupt set enable register */
uint32_t RESERVED0[15U];
__IOM uint32_t IWER[1U]; /*!< Offset: 0x040 (R/W) Interrupt wake-up set register */
uint32_t RESERVED1[15U];
__IOM uint32_t ICER[1U]; /*!< Offset: 0x080 (R/W) Interrupt clear enable register */
uint32_t RESERVED2[15U];
__IOM uint32_t IWDR[1U]; /*!< Offset: 0x0c0 (R/W) Interrupt wake-up clear register */
uint32_t RESERVED3[15U];
__IOM uint32_t ISPR[1U]; /*!< Offset: 0x100 (R/W) Interrupt set pend register */
uint32_t RESERVED4[15U];
__IOM uint32_t ISSR[1U]; /*!< Offset: 0x140 (R/W) Security interrupt set register */
uint32_t RESERVED5[15U];
__IOM uint32_t ICPR[1U]; /*!< Offset: 0x180 (R/W) Interrupt clear pend register */
uint32_t RESERVED6[31U];
__IOM uint32_t IABR[1U]; /*!< Offset: 0x200 (R/W) Interrupt answer stateregister */
uint32_t RESERVED7[63U];
__IOM uint32_t IPR[8U]; /*!< Offset: 0x300 (R/W) Interrupt priority register */
uint32_t RESERVED8[504U];
__IM uint32_t ISR; /*!< Offset: 0xB00 (R/ ) Interrupt state register */
__IOM uint32_t IPTR; /*!< Offset: 0xB04 (R/W) Interrupt priority thershold register */
} VIC_Type;
/*@} end of group CSI_VIC */
/**
\ingroup CSI_core_register
\defgroup CSI_SysTick System Tick Timer (CORET)
\brief Type definitions for the System Timer Registers.
@{
*/
/**
\brief The data structure of the access system timer.
*/
typedef struct {
__IOM uint32_t CTRL; /*!< Offset: 0x000 (R/W) Control register */
__IOM uint32_t LOAD; /*!< Offset: 0x004 (R/W) Backfill register */
__IOM uint32_t VAL; /*!< Offset: 0x008 (R/W) Current register */
__IM uint32_t CALIB; /*!< Offset: 0x00C (R/ ) Calibration register */
} CORET_Type;
/* CORET Control / Status Register Definitions */
#define CORET_CTRL_COUNTFLAG_Pos 16U /*!< CORET CTRL: COUNTFLAG Position */
#define CORET_CTRL_COUNTFLAG_Msk (1UL << CORET_CTRL_COUNTFLAG_Pos) /*!< CORET CTRL: COUNTFLAG Mask */
#define CORET_CTRL_CLKSOURCE_Pos 2U /*!< CORET CTRL: CLKSOURCE Position */
#define CORET_CTRL_CLKSOURCE_Msk (1UL << CORET_CTRL_CLKSOURCE_Pos) /*!< CORET CTRL: CLKSOURCE Mask */
#define CORET_CTRL_TICKINT_Pos 1U /*!< CORET CTRL: TICKINT Position */
#define CORET_CTRL_TICKINT_Msk (1UL << CORET_CTRL_TICKINT_Pos) /*!< CORET CTRL: TICKINT Mask */
#define CORET_CTRL_ENABLE_Pos 0U /*!< CORET CTRL: ENABLE Position */
#define CORET_CTRL_ENABLE_Msk (1UL /*<< CORET_CTRL_ENABLE_Pos*/) /*!< CORET CTRL: ENABLE Mask */
/* CORET Reload Register Definitions */
#define CORET_LOAD_RELOAD_Pos 0U /*!< CORET LOAD: RELOAD Position */
#define CORET_LOAD_RELOAD_Msk (0xFFFFFFUL /*<< CORET_LOAD_RELOAD_Pos*/) /*!< CORET LOAD: RELOAD Mask */
/* CORET Current Register Definitions */
#define CORET_VAL_CURRENT_Pos 0U /*!< CORET VAL: CURRENT Position */
#define CORET_VAL_CURRENT_Msk (0xFFFFFFUL /*<< CORET_VAL_CURRENT_Pos*/) /*!< CORET VAL: CURRENT Mask */
/* CORET Calibration Register Definitions */
#define CORET_CALIB_NOREF_Pos 31U /*!< CORET CALIB: NOREF Position */
#define CORET_CALIB_NOREF_Msk (1UL << CORET_CALIB_NOREF_Pos) /*!< CORET CALIB: NOREF Mask */
#define CORET_CALIB_SKEW_Pos 30U /*!< CORET CALIB: SKEW Position */
#define CORET_CALIB_SKEW_Msk (1UL << CORET_CALIB_SKEW_Pos) /*!< CORET CALIB: SKEW Mask */
#define CORET_CALIB_TENMS_Pos 0U /*!< CORET CALIB: TENMS Position */
#define CORET_CALIB_TENMS_Msk (0xFFFFFFUL /*<< CORET_CALIB_TENMS_Pos*/) /*!< CORET CALIB: TENMS Mask */
/*@} end of group CSI_SysTick */
/**
\ingroup CSI_core_register
\defgroup CSI_DCC
\brief Type definitions for the DCC.
@{
*/
/**
\brief Access to the data structure of DCC.
*/
typedef struct {
uint32_t RESERVED0[13U];
__IOM uint32_t HCR; /*!< Offset: 0x034 (R/W) */
__IM uint32_t EHSR; /*!< Offset: 0x03C (R/ ) */
uint32_t RESERVED1[6U];
union {
__IM uint32_t DERJW; /*!< Offset: 0x058 (R/ ) Data exchange register CPU read*/
__OM uint32_t DERJR; /*!< Offset: 0x058 ( /W) Data exchange register CPU writer*/
};
} DCC_Type;
#define DCC_HCR_JW_Pos 18U /*!< DCC HCR: jw_int_en Position */
#define DCC_HCR_JW_Msk (1UL << DCC_HCR_JW_Pos) /*!< DCC HCR: jw_int_en Mask */
#define DCC_HCR_JR_Pos 19U /*!< DCC HCR: jr_int_en Position */
#define DCC_HCR_JR_Msk (1UL << DCC_HCR_JR_Pos) /*!< DCC HCR: jr_int_en Mask */
#define DCC_EHSR_JW_Pos 1U /*!< DCC EHSR: jw_vld Position */
#define DCC_EHSR_JW_Msk (1UL << DCC_EHSR_JW_Pos) /*!< DCC EHSR: jw_vld Mask */
#define DCC_EHSR_JR_Pos 2U /*!< DCC EHSR: jr_vld Position */
#define DCC_EHSR_JR_Msk (1UL << DCC_EHSR_JR_Pos) /*!< DCC EHSR: jr_vld Mask */
/*@} end of group CSI_DCC */
/**
\ingroup CSI_core_register
\defgroup CSI_core_bitfield Core register bit field macros
\brief Macros for use with bit field definitions (xxx_Pos, xxx_Msk).
@{
*/
/**
\brief Mask and shift a bit field value for use in a register bit range.
\param[in] field Name of the register bit field.
\param[in] value Value of the bit field.
\return Masked and shifted value.
*/
#define _VAL2FLD(field, value) ((value << field ## _Pos) & field ## _Msk)
/**
\brief Mask and shift a register value to extract a bit filed value.
\param[in] field Name of the register bit field.
\param[in] value Value of register.
\return Masked and shifted bit field value.
*/
#define _FLD2VAL(field, value) ((value & field ## _Msk) >> field ## _Pos)
/*@} end of group CSI_core_bitfield */
/**
\ingroup CSI_core_register
\defgroup CSI_core_base Core Definitions
\brief Definitions for base addresses, unions, and structures.
@{
*/
/* Memory mapping of CK801 Hardware */
#define TCIP_BASE (0xE000E000UL) /*!< Titly Coupled IP Base Address */
#define CORET_BASE (TCIP_BASE + 0x0010UL) /*!< CORET Base Address */
#define VIC_BASE (TCIP_BASE + 0x0100UL) /*!< VIC Base Address */
#define DCC_BASE (0xE0011000UL) /*!< DCC Base Address */
#define CORET ((CORET_Type *) CORET_BASE ) /*!< SysTick configuration struct */
#define VIC ((VIC_Type *) VIC_BASE ) /*!< VIC configuration struct */
#define DCC ((DCC_Type *) DCC_BASE ) /*!< DCC configuration struct */
/*@} */
/*******************************************************************************
* Hardware Abstraction Layer
Core Function Interface contains:
- Core VIC Functions
- Core CORET Functions
- Core Register Access Functions
******************************************************************************/
/**
\defgroup CSI_Core_FunctionInterface Functions and Instructions Reference
*/
/* ########################## VIC functions #################################### */
/**
\ingroup CSI_Core_FunctionInterface
\defgroup CSI_Core_VICFunctions VIC Functions
\brief Functions that manage interrupts and exceptions via the VIC.
@{
*/
/* Interrupt Priorities are WORD accessible only under CSKYv6M */
/* The following MACROS handle generation of the register offset and byte masks */
#define _BIT_SHIFT(IRQn) ( ((((uint32_t)(int32_t)(IRQn)) ) & 0x03UL) * 8UL)
#define _IP_IDX(IRQn) ( (((uint32_t)(int32_t)(IRQn)) >> 2UL) )
extern uint32_t __Vectors[];
/**
\brief Enable External Interrupt
\details Enables a device-specific interrupt in the VIC interrupt controller.
\param [in] IRQn External interrupt number. Value cannot be negative.
*/
__ALWAYS_INLINE void csi_vic_enable_irq(int32_t IRQn)
{
VIC->ISER[0U] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL));
#ifdef CONFIG_SYSTEM_SECURE
VIC->ISSR[0U] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL));
#endif
}
/**
\brief Disable External Interrupt
\details Disables a device-specific interrupt in the VIC interrupt controller.
\param [in] IRQn External interrupt number. Value cannot be negative.
*/
__ALWAYS_INLINE void csi_vic_disable_irq(int32_t IRQn)
{
VIC->ICER[0U] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL));
}
/**
\brief Enable External Secure Interrupt
\details Enables a secure device-specific interrupt in the VIC interrupt controller.
\param [in] IRQn External interrupt number. Value cannot be negative.
*/
__ALWAYS_INLINE void csi_vic_enable_sirq(int32_t IRQn)
{
VIC->ISSR[0U] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL));
}
/**
\brief Get Enabled Interrupt irqnums
\details Reads the enabled interrupt register in the NVIC interrupt controller.
\return Interrput status is enabled.
*/
__ALWAYS_INLINE uint32_t csi_vic_get_enabled_irq(int32_t IRQn)
{
return ((uint32_t)(((VIC->ISER[0U] & (1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL));
}
/**
\brief Get Pending Interrupt
\details Reads the pending register in the VIC and returns the pending bit for the specified interrupt.
\param [in] IRQn Interrupt number.
\return 0 Interrupt status is not pending.
\return 1 Interrupt status is pending.
*/
__ALWAYS_INLINE uint32_t csi_vic_get_pending_irq(int32_t IRQn)
{
return ((uint32_t)(((VIC->ISPR[0U] & (1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL));
}
/**
\brief Set Pending Interrupt
\details Sets the pending bit of an external interrupt.
\param [in] IRQn Interrupt number. Value cannot be negative.
*/
__ALWAYS_INLINE void csi_vic_set_pending_irq(int32_t IRQn)
{
VIC->ISPR[0U] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL));
}
/**
\brief Clear Pending Interrupt
\details Clears the pending bit of an external interrupt.
\param [in] IRQn External interrupt number. Value cannot be negative.
*/
__ALWAYS_INLINE void csi_vic_clear_pending_irq(int32_t IRQn)
{
VIC->ICPR[0U] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL));
}
/**
\brief Get Wake up Interrupt
\details Reads the wake up register in the VIC and returns the pending bit for the specified interrupt.
\param [in] IRQn Interrupt number.
\return 0 Interrupt is not set as wake up interrupt.
\return 1 Interrupt is set as wake up interrupt.
*/
__ALWAYS_INLINE uint32_t csi_vic_get_wakeup_irq(int32_t IRQn)
{
return ((uint32_t)(((VIC->IWER[0U] & (1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL));
}
/**
\brief Set Wake up Interrupt
\details Sets the wake up bit of an external interrupt.
\param [in] IRQn Interrupt number. Value cannot be negative.
*/
__ALWAYS_INLINE void csi_vic_set_wakeup_irq(int32_t IRQn)
{
VIC->IWER[0U] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL));
}
/**
\brief Clear Wake up Interrupt
\details Clears the wake up bit of an external interrupt.
\param [in] IRQn External interrupt number. Value cannot be negative.
*/
__ALWAYS_INLINE void csi_vic_clear_wakeup_irq(int32_t IRQn)
{
VIC->IWDR[0U] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL));
}
/**
\brief Get Active Interrupt
\details Reads the active register in the VIC and returns the active bit for the device specific interrupt.
\param [in] IRQn Device specific interrupt number.
\return 0 Interrupt status is not active.
\return 1 Interrupt status is active.
\note IRQn must not be negative.
*/
__ALWAYS_INLINE uint32_t csi_vic_get_active(int32_t IRQn)
{
return ((uint32_t)(((VIC->IABR[0] & (1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL));
}
/**
\brief Set Threshold register
\details set the threshold register in the VIC.
\param [in] VectThreshold specific vecter threshold.
\param [in] PrioThreshold specific priority threshold.
*/
__ALWAYS_INLINE void csi_vic_set_threshold(uint32_t VectThreshold, uint32_t PrioThreshold)
{
VIC->IPTR = 0x80000000 | (((VectThreshold + 32) & 0xFF) << 8) | ((PrioThreshold & 0x3) << 6);
}
/**
\brief Set Interrupt Priority
\details Sets the priority of an interrupt.
\note The priority cannot be set for every core interrupt.
\param [in] IRQn Interrupt number.
\param [in] priority Priority to set.
*/
__ALWAYS_INLINE void csi_vic_set_prio(int32_t IRQn, uint32_t priority)
{
VIC->IPR[_IP_IDX(IRQn)] = ((uint32_t)(VIC->IPR[_IP_IDX(IRQn)] & ~(0xFFUL << _BIT_SHIFT(IRQn))) |
(((priority << (8U - __VIC_PRIO_BITS)) & (uint32_t)0xFFUL) << _BIT_SHIFT(IRQn)));
}
/**
\brief Get Interrupt Priority
\details Reads the priority of an interrupt.
The interrupt number can be positive to specify an external (device specific) interrupt,
or negative to specify an internal (core) interrupt.
\param [in] IRQn Interrupt number.
\return Interrupt Priority.
Value is aligned automatically to the implemented priority bits of the microcontroller.
*/
__ALWAYS_INLINE uint32_t csi_vic_get_prio(int32_t IRQn)
{
return ((uint32_t)(((VIC->IPR[ _IP_IDX(IRQn)] >> _BIT_SHIFT(IRQn)) & (uint32_t)0xFFUL) >> (8U - __VIC_PRIO_BITS)));
}
/**
\brief Set interrupt handler
\details Set the interrupt handler according to the interrupt num, the handler will be filled in __Vectors[].
\param [in] IRQn Interrupt number.
\param [in] handler Interrupt handler.
*/
__ALWAYS_INLINE void csi_vic_set_vector(int32_t IRQn, uint32_t handler)
{
if (IRQn >= 0 && IRQn < 32) {
__Vectors[32 + IRQn] = handler;
}
}
/**
\brief Get interrupt handler
\details Get the address of interrupt handler function.
\param [in] IRQn Interrupt number.
*/
__ALWAYS_INLINE uint32_t csi_vic_get_vector(int32_t IRQn)
{
if (IRQn >= 0 && IRQn < 32) {
return (uint32_t)__Vectors[32 + IRQn];
}
return 0;
}
/*@} end of CSI_Core_VICFunctions */
/* ################################## SysTick function ############################################ */
/**
\ingroup CSI_Core_FunctionInterface
\defgroup CSI_Core_SysTickFunctions SysTick Functions
\brief Functions that configure the System.
@{
*/
/**
\brief CORE timer Configuration
\details Initializes the System Timer and its interrupt, and starts the System Tick Timer.
Counter is in free running mode to generate periodic interrupts.
\param [in] ticks Number of ticks between two interrupts.
\param [in] IRQn core timer Interrupt number.
\return 0 Function succeeded.
\return 1 Function failed.
\note When the variable <b>__Vendor_SysTickConfig</b> is set to 1, then the
function <b>SysTick_Config</b> is not included. In this case, the file <b><i>device</i>.h</b>
must contain a vendor-specific implementation of this function.
*/
__ALWAYS_INLINE uint32_t csi_coret_config(uint32_t ticks, int32_t IRQn)
{
if ((ticks - 1UL) > CORET_LOAD_RELOAD_Msk) {
return (1UL); /* Reload value impossible */
}
CORET->LOAD = (uint32_t)(ticks - 1UL); /* set reload register */
CORET->VAL = 0UL; /* Load the CORET Counter Value */
CORET->CTRL = CORET_CTRL_CLKSOURCE_Msk |
CORET_CTRL_TICKINT_Msk |
CORET_CTRL_ENABLE_Msk; /* Enable CORET IRQ and CORET Timer */
return (0UL); /* Function successful */
}
/**
\brief get CORE timer reload value
\return CORE timer counter value.
*/
__ALWAYS_INLINE uint32_t csi_coret_get_load(void)
{
return CORET->LOAD;
}
/**
\brief get CORE timer counter value
\return CORE timer counter value.
*/
__ALWAYS_INLINE uint32_t csi_coret_get_value(void)
{
return CORET->VAL;
}
/*@} end of CSI_Core_SysTickFunctions */
/* ##################################### DCC function ########################################### */
/**
\ingroup CSI_Core_FunctionInterface
\defgroup CSI_core_DebugFunctions HAD Functions
\brief Functions that access the HAD debug interface.
@{
*/
/**
\brief HAD Send Character
\details Transmits a character via the HAD channel 0, and
\li Just returns when no debugger is connected that has booked the output.
\li Is blocking when a debugger is connected, but the previous character sent has not been transmitted.
\param [in] ch Character to transmit.
\returns Character to transmit.
*/
__ALWAYS_INLINE uint32_t csi_had_send_char(uint32_t ch)
{
DCC->DERJR = (uint8_t)ch;
return (ch);
}
/**
\brief HAD Receive Character
\details Inputs a character via the external variable \ref HAD_RxBuffer.
\return Received character.
\return -1 No character pending.
*/
__ALWAYS_INLINE int32_t csi_had_receive_char(void)
{
int32_t ch = -1; /* no character available */
if (_FLD2VAL(DCC_EHSR_JW, DCC->EHSR)) {
ch = DCC->DERJW;
}
return (ch);
}
/**
\brief HAD Check Character
\details Checks whether a character is pending for reading in the variable \ref HAD_RxBuffer.
\return 0 No character available.
\return 1 Character available.
*/
__ALWAYS_INLINE int32_t csi_had_check_char(void)
{
return _FLD2VAL(DCC_EHSR_JW, DCC->EHSR); /* no character available */
}
/*@} end of CSI_core_DebugFunctions */
/* ################################## IRQ Functions ############################################ */
/**
\brief Save the Irq context
\details save the psr result before disable irq.
\param [in] irq_num External interrupt number. Value cannot be negative.
*/
__ALWAYS_INLINE uint32_t csi_irq_save(void)
{
uint32_t result;
result = __get_PSR();
__disable_irq();
return(result);
}
/**
\brief Restore the Irq context
\details restore saved primask state.
\param [in] irq_state psr irq state.
*/
__ALWAYS_INLINE void csi_irq_restore(uint32_t irq_state)
{
__set_PSR(irq_state);
}
/*@} end of IRQ Functions */
/**
\brief System Reset
\details Initiates a system reset request to reset the MCU.
*/
__ALWAYS_INLINE void csi_system_reset(void)
{
__DSB(); /* Ensure all outstanding memory accesses included
buffered write are completed before reset */
#ifdef __RESET_CONST
__set_SRCR(__RESET_CONST);
#else
__set_SRCR(0xABCD1234);
#endif
__DSB(); /* Ensure completion of memory access */
for(;;) /* wait until reset */
{
__NOP();
}
}
/* ################################## Old Interfaces ############################################ */
/* These interfaces are deprecated */
#define NVIC_EnableIRQ(IRQn) csi_vic_enable_irq(IRQn)
#define NVIC_DisableIRQ(IRQn) csi_vic_disable_irq(IRQn)
#define NVIC_GetPendingIRQ(IRQn) csi_vic_get_pending_irq(IRQn)
#define NVIC_SetPendingIRQ(IRQn) csi_vic_set_pending_irq(IRQn)
#define NVIC_ClearPendingIRQ(IRQn) csi_vic_clear_pending_irq(IRQn)
#define NVIC_GetWakeupIRQ(IRQn) csi_vic_get_wakeup_irq(IRQn)
#define NVIC_SetWakeupIRQ(IRQn) csi_vic_set_wakeup_irq(IRQn)
#define NVIC_ClearWakeupIRQ(IRQn) csi_vic_clear_wakeup_irq(IRQn)
#define NVIC_GetActive(IRQn) csi_vic_get_active(IRQn)
#define NVIC_SetThreshold(VectThreshold, PrioThreshold) csi_vic_set_threshold(VectThreshold, PrioThreshold)
#define NVIC_SetPriority(IRQn, priority) csi_vic_set_prio(IRQn, priority)
#define NVIC_GetPriority(IRQn) csi_vic_get_prio(IRQn)
#define NVIC_SystemReset() csi_system_reset()
#define SysTick_Config(ticks) csi_coret_config(ticks, CORET_IRQn)
#define CORET_Config(ticks) csi_coret_config(ticks, CORET_IRQn)
/*@} end of Old Interfaces */
#ifdef __cplusplus
}
#endif
#endif /* __CORE_CK801_H_DEPENDANT */
#endif /* __CSI_GENERIC */

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,49 @@
/*
* Copyright (C) 2017 C-SKY Microsystems Co., Ltd. All rights reserved.
*
* 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 csi_core.h
* @brief CSI Core Layer Header File
* @version V1.0
* @date 02. June 2017
******************************************************************************/
#ifndef _CORE_H_
#define _CORE_H_
#include <stdint.h>
#if defined(__CK801__)
#include <core_ck801.h>
#elif defined(__CK802__)
#include <core_ck802.h>
#elif defined(__CK803__) || defined(__CK803S__)
#include <core_ck803.h>
#elif defined(__CK610__)
#include <core_ck610.h>
#endif
#include <csi_gcc.h>
#ifdef __cplusplus
extern "C" {
#endif
#ifdef __cplusplus
}
#endif
#endif /* _CORE_H_ */

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,420 @@
/*
* Copyright (C) 2017 C-SKY Microsystems Co., Ltd. All rights reserved.
*
* 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 ck_adc.c
* @brief CSI Source File for ADC Driver
* @version V1.0
* @date 16. October 2017
******************************************************************************/
#include <csi_config.h>
#include <soc.h>
#include <csi_core.h>
#include <drv_adc.h>
#include <ck_adc.h>
#include <drv_gpio.h>
#include <io.h>
#include <string.h>
#define ADC_START_TRY_TIMES 10
#define ADC_WAIT_DATA_VALID_TIMES 10
#define ERR_ADC(errno) (CSI_DRV_ERRNO_ADC_BASE | errno)
#define ADC_NULL_PARAM_CHK(para) \
do { \
if (para == NULL) { \
return ERR_ADC(DRV_ERROR_PARAMETER); \
} \
} while (0)
typedef struct {
adc_event_cb_t cb_event;
uint32_t data_num;
} ck_adc_priv_t;
extern int32_t target_adc_init(uint32_t channel);
extern int32_t target_get_adc_count(void);
static ck_adc_priv_t adc_instance[CONFIG_ADC_NUM];
static const adc_capabilities_t adc_capabilities = {
.single = 1,
.continuous = 1,
.scan = 1,
.calibration = 0,
.comparator = 1
};
void ck_adc_irqhandler(int idx)
{
ck_adc_priv_t *adc_priv = &adc_instance[idx];
if (HAL_IS_BIT_SET(getreg32(( volatile uint32_t *)CK_ADC_IEFG), ADC_CONVERSION_COMLETED_INTERRUPT_BIT)) {
clear_bit(ADC_CONVERSION_COMLETED_INTERRUPT_BIT, ( volatile uint32_t *)CK_ADC_IEFG);
adc_priv->cb_event(0, ADC_EVENT_CONVERSION_COMPLETE);
}
if (HAL_IS_BIT_SET(getreg32(( volatile uint32_t *)CK_ADC_IEFG), ADC_DATA_OVERWRITE_INTERRUPT_BIT)) {
clear_bit(ADC_DATA_OVERWRITE_INTERRUPT_BIT, ( volatile uint32_t *)CK_ADC_IEFG);
adc_priv->cb_event(0, ADC_EVENT_DATA_OVERWRITE);
}
if (HAL_IS_BIT_SET(getreg32(( volatile uint32_t *)CK_ADC_IEFG), ADC_DATA_COMPARE_RIGHT_INTERRUPT_BIT)) {
clear_bit(ADC_DATA_COMPARE_RIGHT_INTERRUPT_BIT, ( volatile uint32_t *)CK_ADC_IEFG);
adc_priv->cb_event(0, ADC_EVENT_DATA_COMPARE_VALID);
}
}
/**
\brief get adc instance count.
\return adc instance count
*/
int32_t csi_adc_get_instance_count(void)
{
return target_get_adc_count();
}
/**
\brief Initialize adc Interface. 1. Initializes the resources needed for the adc interface 2.registers event callback function.
\param[in] idx adc index.
\param[in] cb_event event call back function \ref adc_event_cb_t
\return return adc handle if success
*/
adc_handle_t csi_adc_initialize(int32_t idx, adc_event_cb_t cb_event)
{
if ((idx < 0) || (idx > (CONFIG_ADC_NUM - 1))) {
return NULL;
}
ck_adc_priv_t *adc_priv = &adc_instance[idx];
adc_priv->cb_event = cb_event;
if (cb_event != NULL) {
csi_vic_enable_irq(ADC_IRQn);
set_bit(ADC_CONVERSION_COMLETED_INTERRUPT_BIT, (volatile uint32_t *)CK_ADC_IE);
}
return (adc_handle_t)adc_priv;
}
/**
\brief De-initialize adc Interface. stops operation and releases the software resources used by the interface
\param[in] handle adc handle to operate.
\return error code
*/
int32_t csi_adc_uninitialize(adc_handle_t handle)
{
ADC_NULL_PARAM_CHK(handle);
ck_adc_priv_t *adc_priv = (ck_adc_priv_t *)handle;
adc_priv->cb_event = NULL;
csi_vic_disable_irq(ADC_IRQn);
return 0;
}
/**
\brief Get driver capabilities.
\param[in] idx adc index.
\return \ref adc_capabilities_t
*/
adc_capabilities_t csi_adc_get_capabilities(int32_t idx)
{
if (idx > (CONFIG_ADC_NUM - 1)) {
adc_capabilities_t ret;
memset(&ret, 0, sizeof(adc_capabilities_t));
return ret;
}
return adc_capabilities;
}
/**
\brief config adc mode.
\param[in] handle adc handle to operate.
\param[in] config adc_conf_t\ref . pointer to adc configuration structure.
\return error code
*/
int32_t csi_adc_config(adc_handle_t handle, adc_conf_t *config)
{
ADC_NULL_PARAM_CHK(handle);
ADC_NULL_PARAM_CHK(config);
ADC_NULL_PARAM_CHK(config->channel_array);
ADC_NULL_PARAM_CHK(config->channel_nbr);
ADC_NULL_PARAM_CHK(config->conv_cnt);
if ((config->trigger != 0) && (config->trigger != 1)) {
return -ADC_PARAM_INVALID;
}
if ((config->intrp_mode != 0) && (config->intrp_mode != 1)) {
return -ADC_PARAM_INVALID;
}
if (config->channel_nbr > (CK_ADC_CH15 + 1)) {
return -ADC_PARAM_INVALID;
}
uint32_t* ch_arr = config->channel_array;
int i = 0;
ck_adc_priv_t *adc_priv = (ck_adc_priv_t *)handle;
if (config->mode == ADC_SINGLE) {
if(config->channel_nbr != 1) {
return -ADC_CHANNEL_ERROR;
}
if (config->conv_cnt != 1) {
return -ADC_PARAM_INVALID;
}
ch_arr = config->channel_array;
if (*ch_arr > CK_ADC_CH15) {
return -ADC_CHANNEL_ERROR;
}
if (target_adc_init(*ch_arr) < 0) {
return -ADC_CHANNEL_ERROR;
}
adc_priv->data_num = 1;
clear_bit(CK_ADC_CR_CMS_2_BIT, (volatile uint32_t *)CK_ADC_CR);
clear_bit(CK_ADC_CR_CMS_1_BIT, (volatile uint32_t *)CK_ADC_CR);
write_bits(4, CK_ADC_CR_AOIC_BASE_BIT, (volatile uint32_t *)CK_ADC_CR, *config->channel_array);
} else if (config->mode == ADC_CONTINUOUS) {
if (config->conv_cnt > CK_ADC_CONTINOUS_MODE_MAX_CONVERT_TIMES || config->conv_cnt == 0) {
return -ADC_CONVERSION_INFO_ERROR;
}
if(config->channel_nbr != 1) {
return -ADC_CONVERSION_INFO_ERROR;
}
ch_arr = config->channel_array;
if ((*ch_arr > CK_ADC_CH15)) {
return -ADC_CHANNEL_ERROR;
}
if (*ch_arr > CK_ADC_CH15) {
return -ADC_CHANNEL_ERROR;
}
if (target_adc_init(*ch_arr) < 0) {
return -ADC_CHANNEL_ERROR;
}
adc_priv->data_num = config->conv_cnt;
set_bit(CK_ADC_CR_CMS_2_BIT, (volatile uint32_t *)CK_ADC_CR);
clear_bit(CK_ADC_CR_CMS_1_BIT, (volatile uint32_t *)CK_ADC_CR);
write_bits(4, CK_ADC_CR_SEQC_BASE_BIT, (volatile uint32_t *)CK_ADC_CR, config->conv_cnt - 1);
write_bits(4, CK_ADC_CR_AOIC_BASE_BIT, (volatile uint32_t *)CK_ADC_CR, *ch_arr);
} else if (config->mode == ADC_SCAN) {
if (config->conv_cnt != CK_ADC_SCAN_MODE_MAX_CONVERT_TIMES) {
return -ADC_CONVERSION_INFO_ERROR;
}
if(config->channel_nbr > (CK_ADC_CH15 + 1)) {
return -ADC_CHANNEL_ERROR;
}
for (i = 0; i< config->channel_nbr; i++) {
if ((*ch_arr > CK_ADC_CH15)) {
return -ADC_CHANNEL_ERROR;
}
if (i > 0) {
if ((*ch_arr ) != ((*(ch_arr - 1)) + 1)) {
return -ADC_CHANNEL_ERROR;
}
}
ch_arr ++;
}
ch_arr = config->channel_array;
for (i = 0; i< config->channel_nbr; i++) {
if (target_adc_init(*ch_arr) < 0) {
return -ADC_CHANNEL_ERROR;
}
ch_arr ++;
}
adc_priv->data_num = config->channel_nbr;
clear_bit(CK_ADC_CR_CMS_2_BIT, (volatile uint32_t *)CK_ADC_CR);
set_bit(CK_ADC_CR_CMS_1_BIT, (volatile uint32_t *)CK_ADC_CR);
write_bits(4, CK_ADC_CR_AOIC_BASE_BIT, (volatile uint32_t *)CK_ADC_CR, i);
} else {
return -ADC_MODE_ERROR;
}
return 0;
}
int32_t csi_adc_comparator_config(adc_handle_t handle, adc_cmp_conf_t *config)
{
ADC_NULL_PARAM_CHK(handle);
ADC_NULL_PARAM_CHK(config);
if (config->cmp_channel > CK_ADC_CH15) {
return -ADC_CHANNEL_ERROR;
}
set_bit(CK_ADC_CMPR_CMPEN_BIT, (volatile uint32_t *)CK_ADC_CMPR);
write_bits(1, CK_ADC_CMPR_CMPCOND_BIT, (volatile uint32_t *)CK_ADC_CMPR, config->cmp_condition);
write_bits(4, CK_ADC_CMPR_CMPCH_BASE_BIT, (volatile uint32_t *)CK_ADC_CMPR, config->cmp_channel);
write_bits(4, CK_ADC_CMPR_CMPD_BASE_BIT, (volatile uint32_t *)CK_ADC_CMPR, config->cmp_data);
write_bits(4, CK_ADC_CMPR_CMPMATCNT_BASE_BIT, (volatile uint32_t *)CK_ADC_CMPR, config->cmp_match_cnt);
set_bit(ADC_DATA_COMPARE_RIGHT_INTERRUPT_BIT, (volatile uint32_t *)CK_ADC_IE);
return 0;
}
/**
\brief start adc.
\param[in] handle adc handle to operate.
\return error code
*/
int32_t csi_adc_start(adc_handle_t handle)
{
ADC_NULL_PARAM_CHK(handle);
uint32_t i = 0;
clear_bit(CK_ADC_CR_ADEN_BIT, (volatile uint32_t *)CK_ADC_CR);
while(!read_bits(1, CK_ADC_CR_ADEN_BIT, (volatile uint32_t *)CK_ADC_CR) && (i < ADC_START_TRY_TIMES)) {
set_bit(CK_ADC_STC_ADSTC_BIT, (volatile uint32_t *)CK_ADC_STC);
i ++;
}
set_bit(CK_ADC_STC_ADSTC_BIT, (volatile uint32_t *)CK_ADC_STC);
return 0;
}
/**
\brief stop adc.
\param[in] handle adc handle to operate.
\return error code
*/
int32_t csi_adc_stop(adc_handle_t handle)
{
ADC_NULL_PARAM_CHK(handle);
clear_bit(CK_ADC_CR_ADEN_BIT, (volatile uint32_t *)CK_ADC_CR);
return 0;
}
/**
\brief receiving data from ADC receiver.
\param[in] handle ADC handle to operate.
\param[out] data Pointer to buffer for data to receive from ADC receiver.
\param[in] num Number of data items to receive.
\return error code
*/
int32_t csi_adc_read(adc_handle_t handle, uint32_t *data, uint32_t num)
{
ADC_NULL_PARAM_CHK(handle);
ADC_NULL_PARAM_CHK(data);
ck_adc_priv_t *adc_priv = (ck_adc_priv_t *)handle;
uint32_t read_num = 0;
uint32_t *pbuf = data;
uint32_t get_mode = 0;
uint32_t real_mode = 0;
get_mode = read_bits(2, CK_ADC_CR_CMS_1_BIT, (volatile uint32_t *)CK_ADC_CR);
real_mode = read_bits(2, CK_ADC_CR_CMS_1_BIT, (volatile uint32_t *)CK_ADC_CR);
if (real_mode == CK_ADC_SINGLE_MODE) {
get_mode = ADC_SINGLE;
} else if (real_mode == CK_ADC_SCAN_MODE) {
get_mode = ADC_SCAN;
} else if ( real_mode == CK_ADC_CONTINUOUS) {
get_mode = ADC_CONTINUOUS;
} else {
return -ADC_MODE_ERROR;
}
set_bit(CK_ADC_STC_ADSTC_BIT, (volatile uint32_t *)CK_ADC_STC);
if (num != adc_priv->data_num) {
return -ADC_PARAM_INVALID;
}
if (get_mode == ADC_SINGLE) {
uint32_t i = 0;
while (i < ADC_WAIT_DATA_VALID_TIMES) {
if ((read_bits(1, CK_ADC_SR_VALID_BIT, (volatile uint32_t *)CK_ADC_SR) == 1)) {
break;
}
}
*pbuf = read_bits(CK_ADC_DATA_WIDTH, CK_ADC_DR_DATA_BASE_BIT, (volatile uint32_t *)CK_ADC_DR);
return SUCCESS;
} else if (get_mode == ADC_CONTINUOUS) {
while (read_num < adc_priv->data_num && (read_bits(1, CK_ADC_SR_VALID_BIT, (volatile uint32_t *)CK_ADC_SR) == 1)){
if (read_num < adc_priv->data_num) {
*pbuf ++= read_bits(CK_ADC_DATA_WIDTH, CK_ADC_DR_DATA_BASE_BIT, (volatile uint32_t *)CK_ADC_DR);
read_num ++;
}
}
if (read_num == adc_priv->data_num) {
return SUCCESS;
} else if (read_num < adc_priv->data_num) {
return -ADC_DATA_LOST;
} else {
return -ADC_DATA_OVERFLOW;
}
} else if (get_mode == ADC_SCAN) {
while (read_num < adc_priv->data_num && (read_bits(1, CK_ADC_SR_VALID_BIT, (volatile uint32_t *)CK_ADC_SR) == 1)) {
if (read_num < adc_priv->data_num) {
*pbuf ++= read_bits(CK_ADC_DATA_WIDTH, CK_ADC_DR_DATA_BASE_BIT, (volatile uint32_t *)CK_ADC_DR);
read_num ++;
}
}
if (read_num == adc_priv->data_num) {
return SUCCESS;
} else if (read_num < adc_priv->data_num) {
return -ADC_DATA_LOST;
} else {
return -ADC_DATA_OVERFLOW;
}
} else {
return -ADC_MODE_ERROR;
}
return -ADC_MODE_ERROR;
}
/**
\brief Get ADC status.
\param[in] handle adc handle to operate.
\return ADC status \ref adc_status_t
*/
adc_status_t csi_adc_get_status(adc_handle_t handle)
{
adc_status_t adc_status = {0};
if (handle == NULL) {
return adc_status;
}
uint32_t get_stat = read_bits(1, CK_ADC_SR_BUSY_BIT, (volatile uint32_t *)CK_ADC_SR);
if (get_stat == 0) {
adc_status.complete = 1;
} else if(get_stat == 1) {
adc_status.busy = 1;
}
return adc_status;
}

View file

@ -0,0 +1,659 @@
/*
* Copyright (C) 2017 C-SKY Microsystems Co., Ltd. All rights reserved.
*
* 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 ck_aes.c
* @brief CSI Source File for aes driver
* @version V1.0
* @date 02. June 2017
******************************************************************************/
#include <csi_config.h>
#include <string.h>
#include "drv_aes.h"
#include "ck_aes.h"
#include "csi_core.h"
#define ERR_AES(errno) (CSI_DRV_ERRNO_AES_BASE | errno)
#define AES_NULL_PARA_CHK(para) \
do { \
if (para == NULL) { \
return ERR_AES(DRV_ERROR_PARAMETER); \
} \
} while (0)
static ck_aes_reg_t *aes_reg = NULL;
volatile static uint8_t block_cal_done = 0;
typedef struct {
uint32_t base;
uint32_t irq;
void *iv;
uint8_t *result_out;
uint32_t len;
aes_event_cb_t cb;
aes_mode_e mode;
aes_key_len_bits_e keylen;
aes_endian_mode_e endian;
aes_crypto_mode_e enc;
aes_status_t status;
} ck_aes_priv_t;
extern int32_t target_get_aes_count(void);
extern int32_t target_get_aes(int32_t idx, uint32_t *base, uint32_t *irq);
static ck_aes_priv_t aes_handle[CONFIG_AES_NUM];
/* Driver Capabilities */
static const aes_capabilities_t driver_capabilities = {
.ecb_mode = 1, /* ECB mode */
.cbc_mode = 1, /* CBC mode */
.cfb1_mode = 0, /* CFB1 mode */
.cfb8_mode = 0, /* CFB8 mode */
.cfb128_mode = 0, /* CFB128 mode */
.ofb_mode = 0, /* OFB mode */
.ctr_mode = 0, /* CTR mode */
.bits_128 = 1, /* 128bits key length mode */
.bits_192 = 1, /* 192bits key lenght mode */
.bits_256 = 1 /* 256bits key length mode */
};
typedef enum {
AES_PADDING_MODE_NO = 0, ///< NO-PADDING
AES_PADDING_MODE_ZERO , ///< ZERO-PADDING
AES_PADDING_MODE_PKCS5 ///< PKCS5-PADDING
} aes_padding_mode_e;
//
// Functions
//
static inline void aes_set_opcode(aes_crypto_mode_e opcode)
{
aes_reg->ctrl &= ~(3 << AES_OPCODE_OFFSET); //clear bit[7:6]
aes_reg->ctrl |= (opcode << AES_OPCODE_OFFSET); //set opcode
}
static inline void aes_set_endian(aes_endian_mode_e endian)
{
if (endian == AES_ENDIAN_LITTLE) {
aes_reg->ctrl &= ~AES_LITTLE_ENDIAN;
} else {
aes_reg->ctrl |= AES_LITTLE_ENDIAN;
}
}
static inline uint32_t aes_set_keylen(aes_key_len_bits_e keylength)
{
aes_reg->ctrl &= ~(3 << AES_KEY_LEN_OFFSET); //clear bit[5:4]
aes_reg->ctrl |= (keylength << AES_KEY_LEN_OFFSET);// Set key length
return 0;
}
static inline void aes_set_mode(aes_mode_e mode)
{
aes_reg->ctrl &= ~(1 << AES_MODE_OFFSET); //clear bit 3
aes_reg->ctrl |= (mode << AES_MODE_OFFSET); //set mode
}
static inline void aes_enable(void)
{
aes_reg->ctrl |= (1 << AES_WORK_ENABLE_OFFSET);
}
static inline void aes_disable(void)
{
aes_reg->ctrl &= ~(1 << AES_WORK_ENABLE_OFFSET);
}
static inline void aes_enable_interrupt(void)
{
aes_reg->ctrl |= (1 << AES_INT_ENABLE_OFFSET);
}
static inline void aes_disable_interrupt(void)
{
aes_reg->ctrl &= ~(1 << AES_INT_ENABLE_OFFSET);
}
static inline void aes_clear_interrupt(void)
{
aes_reg->state = 0x0;
}
static inline uint32_t aes_get_intstatus(uint32_t AES_IT)
{
return (aes_reg->state & AES_IT) ? 1 : 0;
}
static void aes_set_key(void *context, uint8_t *key, aes_key_len_bits_e keylen, uint32_t enc, uint32_t endian)
{
uint8_t keynum = 0;
if (keylen == AES_KEY_LEN_BITS_128) {
keynum = 4;
} else if (keylen == AES_KEY_LEN_BITS_192) {
keynum = 6;
} else if (keylen == AES_KEY_LEN_BITS_256) {
keynum = 8;
}
uint32_t i;
uint32_t temp = 0;
/* set key according to the endian mode */
if (endian == AES_ENDIAN_LITTLE) {
for (i = 0; i < keynum; i++) {
temp = key[3] << 24 | key[2] << 16 | key[1] << 8 | key[0];
aes_reg->key[keynum - 1 - i] = temp;
key += 4;
}
} else if (endian == AES_ENDIAN_BIG) {
for (i = 0; i < keynum; i++) {
temp = key[3] << 24 | key[2] << 16 | key[1] << 8 | key[0];
aes_reg->key[i] = temp;
key += 4;
}
}
if (enc == AES_CRYPTO_MODE_DECRYPT) {
aes_set_opcode(AES_CRYPTO_KEYEXP); /* if the mode is decrypt before decrypt you have to keyexpand */
aes_enable();
// while(block_cal_done == 0);
// block_cal_done = 0;
while (aes_get_intstatus(AES_IT_KEYINT));
aes_set_opcode(AES_CRYPTO_MODE_DECRYPT);
} else if (enc == AES_CRYPTO_MODE_ENCRYPT) {
aes_set_opcode(AES_CRYPTO_MODE_ENCRYPT);
}
aes_disable();
}
static void aes_set_iv(uint32_t mode, uint32_t endian, uint8_t *iv)
{
uint32_t temp;
uint32_t i;
/* set iv if the mode is CBC */
if (mode == AES_MODE_CBC) {
if (endian == AES_ENDIAN_BIG) {
for (i = 0; i < 4; i++) {
temp = iv[3] << 24 | iv[2] << 16 | iv[1] << 8 | iv[0];
aes_reg->iv[i] = temp;
iv += 4;
}
} else if (endian == AES_ENDIAN_LITTLE) {
for (i = 0; i < 4; i++) {
temp = iv[3] << 24 | iv[2] << 16 | iv[1] << 8 | iv[0];
aes_reg->iv[3 - i] = temp;
iv += 4;
}
}
}
}
static int aes_crypto(void *context, uint8_t *in, uint8_t *out,
uint32_t len, uint8_t *iv, uint32_t mode, uint32_t endian, uint32_t enc)
{
uint32_t temp[4];
aes_set_iv(mode, endian, iv);
uint32_t i = 0;
uint32_t j = 0;
/* set the text before aes calculating */
for (i = 0; i < len; i = i + 16) {
for (j = 0; j < 4; j++) {
temp[j] = in[3] << 24 | in[2] << 16 | in[1] << 8 | in[0];
if (endian == AES_ENDIAN_BIG) {
aes_reg->datain[j] = temp[j];
} else if (endian == AES_ENDIAN_LITTLE) {
aes_reg->datain[3 - j] = temp[j];
}
in += 4;
}
aes_enable();
while(block_cal_done == 0);
block_cal_done = 0;
if (enc == AES_CRYPTO_MODE_ENCRYPT && mode == AES_MODE_CBC) {
aes_set_iv(mode, endian, out);
memcpy(iv, out, 16);
out += 16;
} else if (enc == AES_CRYPTO_MODE_DECRYPT && mode == AES_MODE_CBC) {
aes_set_iv(mode, endian, (uint8_t *)&temp);
memcpy(iv, temp, 16);
}
}
return 0;
}
void ck_aes_irqhandler(int32_t idx)
{
ck_aes_priv_t *aes_priv = &aes_handle[idx];
volatile uint32_t j;
uint32_t tmp = 0;
/* get the result after aes calculating*/
if (aes_priv->result_out != NULL) {
for (j = 0; j < 4; j++) {
if (aes_priv->endian == AES_ENDIAN_BIG) {
tmp = aes_reg->dataout[j];
} else if (aes_priv->endian == AES_ENDIAN_LITTLE) {
tmp = aes_reg->dataout[3 - j];
}
memcpy(aes_priv->result_out, &tmp, 4);
aes_priv->result_out += 4;
aes_priv->len -= 4;
}
}
block_cal_done = 1;
/* disable aes and clear the aes interrupt */
aes_disable();
aes_clear_interrupt();
/* execute the callback function */
if (aes_priv->len == 0) {
if (aes_priv->cb) {
aes_priv->cb(idx, AES_EVENT_CRYPTO_COMPLETE);
}
}
}
/**
\brief Initialize AES Interface. 1. Initializes the resources needed for the AES interface 2.registers event callback function
\param[in] idx device id
\param[in] cb_event Pointer to \ref aes_event_cb_t
\return return aes handle if success
*/
aes_handle_t csi_aes_initialize(int32_t idx, aes_event_cb_t cb_event)
{
if (idx < 0 || idx >= CONFIG_AES_NUM) {
return NULL;
}
uint32_t irq = 0u;
uint32_t base = 0u;
/* obtain the aes information */
int32_t real_idx = target_get_aes(idx, &base, &irq);
if (real_idx != idx) {
return NULL;
}
ck_aes_priv_t *aes_priv = &aes_handle[idx];
aes_priv->base = base;
aes_priv->irq = irq;
/* initialize the aes context */
aes_reg = (ck_aes_reg_t *)(aes_priv->base);
aes_priv->cb = cb_event;
aes_priv->iv = NULL;
aes_priv->len = 16;
aes_priv->result_out = NULL;
aes_priv->mode = AES_MODE_CBC;
aes_priv->keylen = AES_KEY_LEN_BITS_128;
aes_priv->endian = AES_ENDIAN_LITTLE;
aes_priv->status.busy = 0;
aes_enable_interrupt(); /* enable the aes interrupt */
csi_vic_enable_irq(aes_priv->irq); /* enable the aes bit in vic */
return (aes_handle_t)aes_priv;
}
/**
\brief De-initialize AES Interface. stops operation and releases the software resources used by the interface
\param[in] handle aes handle to operate.
\return error code
*/
int32_t csi_aes_uninitialize(aes_handle_t handle)
{
AES_NULL_PARA_CHK(handle);
ck_aes_priv_t *aes_priv = handle;
aes_priv->cb = NULL;
aes_disable_interrupt(); /* disable the aes interrupt */
csi_vic_disable_irq(aes_priv->irq);
return 0;
}
/**
\brief Get driver capabilities.
\param[in] idx device id.
\return \ref aes_capabilities_t
*/
aes_capabilities_t csi_aes_get_capabilities(int32_t idx)
{
if (idx < 0 || idx >= CONFIG_AES_NUM) {
aes_capabilities_t ret;
memset(&ret, 0, sizeof(aes_capabilities_t));
return ret;
}
return driver_capabilities;
}
/**
\brief config aes mode.
\param[in] handle aes handle to operate.
\param[in] mode \ref aes_mode_e
\param[in] keylen_bits \ref aes_key_len_bits_e
\param[in] endian \ref aes_endian_mode_e
\return error code
*/
int32_t csi_aes_config(aes_handle_t handle, aes_mode_e mode, aes_key_len_bits_e keylen_bits, aes_endian_mode_e endian)
{
AES_NULL_PARA_CHK(handle);
ck_aes_priv_t *aes_priv = handle;
aes_reg = (ck_aes_reg_t *)(aes_priv->base);
/* config the aes mode */
switch (mode) {
case AES_MODE_CBC:
aes_priv->mode = mode;
aes_set_mode(mode);
break;
case AES_MODE_ECB:
aes_priv->mode = mode;
aes_set_mode(mode);
break;
case AES_MODE_CFB1:
case AES_MODE_CFB8:
case AES_MODE_CFB128:
case AES_MODE_OFB:
case AES_MODE_CTR:
return ERR_AES(DRV_ERROR_UNSUPPORTED);
default:
return ERR_AES(AES_ERROR_MODE);
}
/* config the key length */
switch (keylen_bits) {
case AES_KEY_LEN_BITS_128:
case AES_KEY_LEN_BITS_192:
case AES_KEY_LEN_BITS_256:
aes_priv->keylen = keylen_bits;
aes_set_keylen(keylen_bits);
break;
default:
return ERR_AES(AES_ERROR_DATA_BITS);
}
/* config the endian mode */
switch (endian) {
case AES_ENDIAN_LITTLE:
aes_priv->endian = endian;
aes_set_endian(endian);
break;
case AES_ENDIAN_BIG:
aes_priv->endian = endian;
aes_set_endian(endian);
break;
default:
return ERR_AES(AES_ERROR_ENDIAN);
}
return 0;
}
/**
\brief set crypto key.
\param[in] handle aes handle to operate.
\param[in] context aes information context(NULL when hardware implementation)
\param[in] key Pointer to the key buf
\param[in] key_len Pointer to the aes_key_len_bits_e
\param[in] enc \ref aes_crypto_mode_e
\return error code
*/
int32_t csi_aes_set_key(aes_handle_t handle, void *context, void *key, aes_key_len_bits_e key_len, aes_crypto_mode_e enc)
{
AES_NULL_PARA_CHK(handle);
AES_NULL_PARA_CHK(key);
if ((key_len != AES_KEY_LEN_BITS_128 &&
key_len != AES_KEY_LEN_BITS_192 &&
key_len != AES_KEY_LEN_BITS_256) ||
(enc != AES_CRYPTO_MODE_ENCRYPT &&
enc != AES_CRYPTO_MODE_DECRYPT)) {
return ERR_AES(DRV_ERROR_PARAMETER);
}
ck_aes_priv_t *aes_priv = handle;
aes_priv->enc = enc;
aes_set_key(context, key, key_len, enc, aes_priv->endian);
return 0;
}
/**
\brief encrypt or decrypt
\param[in] handle aes handle to operate.
\param[in] context aes information context(NULL when hardware implementation)
\param[in] in Pointer to the Source data
\param[out] out Pointer to the Result data.
\param[in] len the Source data len.
\param[in] padding \ref aes_padding_mode_e.
\return error code
*/
int32_t csi_aes_crypto(aes_handle_t handle, void *context, void *in, void *out, uint32_t len, aes_padding_mode_e padding)
{
AES_NULL_PARA_CHK(handle);
AES_NULL_PARA_CHK(in);
AES_NULL_PARA_CHK(out);
AES_NULL_PARA_CHK(len);
ck_aes_priv_t *aes_priv = handle;
aes_priv->status.busy = 1;
uint8_t left_len = len & 0xf;
switch (padding) {
case AES_PADDING_MODE_NO:
if (left_len) {
return ERR_AES(DRV_ERROR_PARAMETER);
}
/* crypto in padding no mode */
aes_priv->result_out = out;
aes_priv->len = len;
aes_crypto(context, in, out, len, aes_priv->iv, aes_priv->mode, aes_priv->endian, aes_priv->enc);
break;
case AES_PADDING_MODE_ZERO:
if (left_len == 0) {
return ERR_AES(DRV_ERROR_PARAMETER);
}
uint8_t i = 0;
for (i = 0; i < (16 - left_len); i++) {
*((uint8_t *)in + len + i) = 0x0;
}
/* crypto in padding zero mode */
aes_priv->result_out = out;
aes_priv->len = len + 16 -left_len;
aes_crypto(context, in, out, len + 16 - left_len, aes_priv->iv, aes_priv->mode, aes_priv->endian, aes_priv->enc);
break;
case AES_PADDING_MODE_PKCS5:
return ERR_AES(DRV_ERROR_UNSUPPORTED);
default:
return ERR_AES(DRV_ERROR_PARAMETER);
}
aes_priv->status.busy = 0;
return 0;
}
/**
\brief aes ecb encrypt or decrypt
\param[in] handle aes handle to operate.
\param[in] context aes information context(NULL when hardware implementation)
\param[in] in Pointer to the Source data
\param[out] out Pointer to the Result data.
\param[in] len the Source data len.
\return error code
*/
int32_t csi_aes_ecb_crypto(aes_handle_t handle, void *context, void *in, void *out, uint32_t len)
{
AES_NULL_PARA_CHK(handle);
AES_NULL_PARA_CHK(in);
AES_NULL_PARA_CHK(out);
AES_NULL_PARA_CHK(len);
return csi_aes_crypto(handle, context, in, out, len, AES_PADDING_MODE_NO);
}
/**
\brief aes cbc encrypt or decrypt
\param[in] handle aes handle to operate.
\param[in] context aes information context(NULL when hardware implementation)
\param[in] in Pointer to the Source data
\param[out] out Pointer to the Result data.
\param[in] len the Source data len.
\param[in] iv Pointer to initialization vector(updated after use)
\return error code
*/
int32_t csi_aes_cbc_crypto(aes_handle_t handle, void *context, void *in, void *out, uint32_t len, unsigned char iv[16])
{
AES_NULL_PARA_CHK(handle);
AES_NULL_PARA_CHK(in);
AES_NULL_PARA_CHK(out);
AES_NULL_PARA_CHK(len);
AES_NULL_PARA_CHK(iv);
ck_aes_priv_t *aes_priv = handle;
aes_priv->iv = (void *)iv;
return csi_aes_crypto(handle, context, in, out, len, AES_PADDING_MODE_NO);
}
/**
\brief aes cfb1 encrypt or decrypt
\param[in] handle aes handle to operate.
\param[in] context aes information context(NULL when hardware implementation)
\param[in] in Pointer to the Source data
\param[out] out Pointer to the Result data.
\param[in] len the Source data len.
\param[in] iv Pointer to initialization vector(updated after use)
\return error code
*/
int32_t csi_aes_cfb1_crypto(aes_handle_t handle, void *context, void *in, void *out, uint32_t len, unsigned char iv[16])
{
return ERR_AES(DRV_ERROR_UNSUPPORTED);
}
/**
\brief aes cfb8 encrypt or decrypt
\param[in] handle aes handle to operate.
\param[in] context aes information context(NULL when hardware implementation)
\param[in] in Pointer to the Source data
\param[out] out Pointer to the Result data.
\param[in] len the Source data len.
\param[in] iv Pointer to initialization vector(updated after use)
\return error code
*/
int32_t csi_aes_cfb8_crypto(aes_handle_t handle, void *context, void *in, void *out, uint32_t len, unsigned char iv[16])
{
return ERR_AES(DRV_ERROR_UNSUPPORTED);
}
/**
\brief aes cfb128 encrypt or decrypt
\param[in] handle aes handle to operate.
\param[in] context aes information context(NULL when hardware implementation)
\param[in] in Pointer to the Source data
\param[out] out Pointer to the Result data.
\param[in] len the Source data len.
\param[in] iv Pointer to initialization vector(updated after use)
\param[in] num the number of the 128-bit block we have used(updated after use)
\return error code
*/
int32_t csi_aes_cfb128_crypto(aes_handle_t handle, void *context, void *in, void *out, uint32_t len, unsigned char iv[16], uint32_t *num)
{
return ERR_AES(DRV_ERROR_UNSUPPORTED);
}
/**
\brief aes ofb encrypt or decrypt
\param[in] handle aes handle to operate.
\param[in] context aes information context(NULL when hardware implementation)
\param[in] in Pointer to the Source data
\param[out] out Pointer to the Result data.
\param[in] len the Source data len.
\param[in] iv Pointer to initialization vector(updated after use)
\param[in] num the number of the 128-bit block we have used(updated after use)
\return error code
*/
int32_t csi_aes_ofb_crypto(aes_handle_t handle, void *context, void *in, void *out, uint32_t len, unsigned char iv[16], uint32_t *num)
{
return ERR_AES(DRV_ERROR_UNSUPPORTED);
}
/**
\brief aes ofb encrypt or decrypt
\param[in] handle aes handle to operate.
\param[in] context aes information context(NULL when hardware implementation)
\param[in] in Pointer to the Source data
\param[out] out Pointer to the Result data.
\param[in] len the Source data len.
\param[in] nonce_counter Pointer to the 128-bit nonce and counter(updated after use)
\param[in] stream_block Pointer to the saved stream-block for resuming(updated after use)
\param[in] num the number of the 128-bit block we have used(updated after use)
\return error code
*/
int32_t csi_aes_ctr_crypto(aes_handle_t handle, void *context, void *in, void *out, uint32_t len, unsigned char nonce_counter[16],
unsigned char stream_block[16], uint32_t *num)
{
return ERR_AES(DRV_ERROR_UNSUPPORTED);
}
/**
\brief Get AES status.
\param[in] handle aes handle to operate.
\return AES status \ref aes_status_t
*/
aes_status_t csi_aes_get_status(aes_handle_t handle)
{
if (handle == NULL) {
aes_status_t ret;
memset(&ret, 0, sizeof(aes_status_t));
return ret;
}
ck_aes_priv_t *aes_priv = handle;
return aes_priv->status;
}

View file

@ -0,0 +1,274 @@
/*
* Copyright (C) 2017 C-SKY Microsystems Co., Ltd. All rights reserved.
*
* 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 ck_crc.c
* @brief CSI Source File for CRC Driver
* @version V1.0
* @date 02. June 2017
******************************************************************************/
#include <csi_config.h>
#include <stdio.h>
#include <string.h>
#include "drv_crc.h"
#include "ck_crc.h"
#define ERR_CRC(errno) (CSI_DRV_ERRNO_CRC_BASE | errno)
#define CRC_NULL_PARAM_CHK(para) \
do { \
if (para == NULL) { \
return ERR_CRC(DRV_ERROR_PARAMETER); \
} \
} while (0)
typedef struct {
uint32_t base;
crc_event_cb_t cb;
crc_status_t status;
} ck_crc_priv_t;
extern int32_t target_get_crc_count(void);
extern int32_t target_get_crc(int32_t idx, uint32_t *base);
static ck_crc_priv_t crc_handle[CONFIG_CRC_NUM];
/* Driver Capabilities */
static const crc_capabilities_t driver_capabilities = {
.ROHC = 1, /* ROHC mode */
.MAXIM = 1, /* MAXIM mode */
.X25 = 1, /* X25 mode */
.CCITT = 1, /* CCITT mode */
.USB = 1, /* USB mode */
.IBM = 1, /* IBM mode */
.MODBUS = 1 /* MODBUS mode */
};
//
// Functions
//
static ck_crc_reg_t *crc_reg = NULL;
static int32_t crc_set_mode(crc_mode_e mode, crc_standard_crc_e standard)
{
if (mode == CRC_MODE_CRC16) {
switch (standard) {
case CRC_STANDARD_CRC_MODBUS:
crc_reg->CRC_SEL = 0x0;
crc_reg->CRC_INIT = 0xffff;
break;
case CRC_STANDARD_CRC_IBM:
crc_reg->CRC_SEL = 0x0;
crc_reg->CRC_INIT = 0x0;
break;
case CRC_STANDARD_CRC_MAXIM:
crc_reg->CRC_SEL = 0x4;
crc_reg->CRC_INIT = 0x0;
break;
case CRC_STANDARD_CRC_USB:
crc_reg->CRC_SEL = 0x4;
crc_reg->CRC_INIT = 0xffff;
break;
case CRC_STANDARD_CRC_CCITT:
crc_reg->CRC_SEL = 0x1;
crc_reg->CRC_INIT = 0x0;
break;
case CRC_STANDARD_CRC_X25:
crc_reg->CRC_SEL = 0x5;
crc_reg->CRC_INIT = 0xffff;
break;
default:
return ERR_CRC(DRV_ERROR_PARAMETER);
}
} else if (mode == CRC_MODE_CRC8) {
switch (standard) {
case CRC_STANDARD_CRC_MAXIM:
crc_reg->CRC_SEL = 0x2;
crc_reg->CRC_INIT = 0x0;
break;
case CRC_STANDARD_CRC_ROHC:
crc_reg->CRC_SEL = 0x3;
crc_reg->CRC_INIT = 0xff;
break;
default:
return ERR_CRC(DRV_ERROR_PARAMETER);
}
} else {
return ERR_CRC(DRV_ERROR_PARAMETER);
}
return 0;
}
static int32_t crc_set_data(uint32_t data)
{
crc_reg->CRC_DATA = data;
return 0;
}
static int32_t crc_get_data(uint32_t *data)
{
*data = crc_reg->CRC_DATA;
return 0;
}
/**
\brief Initialize CRC Interface. 1. Initializes the resources needed for the CRC interface 2.registers event callback function
\param[in] idx must not exceed return value of csi_crc_get_handle_count()
\param[in] cb_event Pointer to \ref crc_event_cb_t
\return return crc handle if success
*/
crc_handle_t csi_crc_initialize(int32_t idx, crc_event_cb_t cb_event)
{
if (idx < 0 || idx >= CONFIG_CRC_NUM) {
return NULL;
}
/* obtain the crc information */
uint32_t base = 0u;
int32_t real_idx = target_get_crc(idx, &base);
if (real_idx != idx) {
return NULL;
}
ck_crc_priv_t *crc_priv = &crc_handle[idx];
crc_priv->base = base;
crc_priv->cb = cb_event;
crc_priv->status.busy = 0;
crc_reg = (ck_crc_reg_t *)(crc_priv->base);
return (crc_handle_t)crc_priv;
}
/**
\brief De-initialize CRC Interface. stops operation and releases the software resources used by the interface
\param[in] handle crc handle to operate.
\return error code
*/
int32_t csi_crc_uninitialize(crc_handle_t handle)
{
CRC_NULL_PARAM_CHK(handle);
ck_crc_priv_t *crc_priv = handle;
crc_priv->cb = NULL;
return 0;
}
/**
\brief Get driver capabilities.
\param[in] idx device id.
\return \ref crc_capabilities_t
*/
crc_capabilities_t csi_crc_get_capabilities(int32_t idx)
{
if (idx < 0 || idx >= CONFIG_CRC_NUM) {
crc_capabilities_t ret;
memset(&ret, 0, sizeof(crc_capabilities_t));
return ret;
}
return driver_capabilities;
}
/**
\brief config crc mode.
\param[in] handle crc handle to operate.
\param[in] mode \ref crc_mode_e
\param[in] standard \ref crc_standard_crc_e
\return error code
*/
int32_t csi_crc_config(crc_handle_t handle, crc_mode_e mode, crc_standard_crc_e standard)
{
CRC_NULL_PARAM_CHK(handle);
/* set the crc mode */
uint32_t ret = crc_set_mode(mode, standard);
return ret;
}
/**
\brief calculate crc.
\param[in] handle crc handle to operate.
\param[in] in Pointer to the input data
\param[out] out Pointer to the result.
\param[in] len intpu data len.
\return error code
*/
int32_t csi_crc_calculate(crc_handle_t handle, const void *in, void *out, uint32_t len)
{
CRC_NULL_PARAM_CHK(handle);
CRC_NULL_PARAM_CHK(in);
CRC_NULL_PARAM_CHK(out);
if (len <= 0) {
return ERR_CRC(DRV_ERROR_PARAMETER);
}
ck_crc_priv_t *crc_priv = handle;
crc_reg = (ck_crc_reg_t *)(crc_priv->base);
crc_priv->status.busy = 1;
/* put the data int the register */
uint8_t cur;
uint8_t *p = (uint8_t *)in;
for (cur=0; cur<len - 3; cur += 4, p+=4) {
crc_set_data(p[0]
| (p[1] << 8)
| (p[2] << 16)
| (p[3] << 24));
}
uint32_t data = 0;
uint8_t i;
if (cur < len) {
for (i=0; i<len-cur; i++) {
data |= (p[cur + i] << (i*8));
}
crc_set_data(data);
}
crc_get_data((uint32_t *)out);
crc_priv->status.busy = 0;
return 0;
}
/**
\brief Get CRC status.
\param[in] handle crc handle to operate.
\return CRC status \ref crc_status_t
*/
crc_status_t csi_crc_get_status(crc_handle_t handle)
{
if (handle == NULL) {
crc_status_t ret;
memset(&ret, 0, sizeof(crc_status_t));
return ret;
}
ck_crc_priv_t *crc_priv = handle;
return crc_priv->status;
}

View file

@ -0,0 +1,510 @@
/*
* Copyright (C) 2017 C-SKY Microsystems Co., Ltd. All rights reserved.
*
* 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 ck_dmac.c
* @brief CSI Source File for DMAC Driver
* @version V1.0
* @date 02. June 2017
******************************************************************************/
#include <csi_config.h>
#include <stdbool.h>
#include "ck_dmac.h"
#include "csi_core.h"
#include "drv_dmac.h"
#include "soc.h"
#include <string.h>
#define ERR_DMA(errno) (CSI_DRV_ERRNO_DMA_BASE | errno)
typedef struct {
uint32_t base;
uint32_t irq;
dma_event_cb_t cb_event;
uint8_t ch_num;
} ck_dma_priv_t;
extern int32_t target_get_dmac(int32_t idx, uint32_t *base, uint32_t *irq);
extern int32_t target_get_dmac_count(void);
static ck_dma_priv_t dma_instance[CONFIG_DMAC_NUM];
static const dma_capabilities_t dma_capabilities = {
.unalign_addr = 1, ///< support for unalign address transfer when memory is source
};
static volatile dma_status_e status[CK_DMA_MAXCHANNEL] = {DMA_STATE_FREE, DMA_STATE_FREE};
static volatile uint8_t ch_opened[CK_DMA_MAXCHANNEL] = {0, 0};
static int32_t ck_dma_set_channel(ck_dma_reg_t *addr, uint32_t source, uint32_t dest, uint32_t size)
{
uint32_t temp = addr->CHCTRLA;
temp &= 0xff000fff;
temp |= (size << 12);
addr->SAR = source;
addr->DAR = dest ;
addr->CHCTRLA = temp;
return 0;
}
static int32_t ck_dma_set_transfertype(ck_dma_reg_t *addr, dma_trans_type_e transtype)
{
uint32_t temp = addr->CHCTRLB;
temp &= 0xffffff7f;
if (transtype >= DMA_PERH2PERH) {
return ERR_DMA(DRV_ERROR_PARAMETER);
}
if (transtype == DMA_MEM2MEM) {
temp |= (transtype << 7);
} else {
temp |= (1 << 7);
}
addr->CHCTRLB = temp;
return 0;
}
static int32_t ck_dma_set_addrinc(ck_dma_reg_t *addr, enum_addr_state_e src_addrinc, enum_addr_state_e dst_addrinc)
{
if ((src_addrinc != DMA_ADDR_INCREMENT && src_addrinc != DMA_ADDR_DECREMENT && src_addrinc != DMA_ADDR_NOCHANGE) ||
(dst_addrinc != DMA_ADDR_INCREMENT && dst_addrinc != DMA_ADDR_DECREMENT && dst_addrinc != DMA_ADDR_NOCHANGE)) {
return ERR_DMA(DRV_ERROR_PARAMETER);
}
uint32_t temp = addr->CHCTRLA;
temp &= 0xffffff0f;
temp |= (src_addrinc << 6);
temp |= (dst_addrinc << 4);
addr->CHCTRLA = temp;
return 0;
}
static int32_t ck_dma_set_transferwidth(ck_dma_reg_t *addr, dma_datawidth_e src_width, dma_datawidth_e dst_width)
{
if ((src_width != DMA_DATAWIDTH_SIZE8 && src_width != DMA_DATAWIDTH_SIZE16 && src_width != DMA_DATAWIDTH_SIZE32) ||
(dst_width != DMA_DATAWIDTH_SIZE8 && dst_width != DMA_DATAWIDTH_SIZE16 && dst_width != DMA_DATAWIDTH_SIZE32)) {
return ERR_DMA(DRV_ERROR_PARAMETER);
}
uint32_t temp = addr->CHCTRLA;
temp &= 0xfffffff0;
temp |= (src_width - 1) << 2;
temp |= dst_width - 1;
addr->CHCTRLA = temp;
return 0;
}
static int32_t ck_dma_set_burstlength(ck_dma_reg_t *addr, uint8_t burstlength)
{
uint32_t temp = addr->CHCTRLA;
temp &= 0xfffff0ff;
temp |= (burstlength << 8);
addr->CHCTRLA = temp;
return 0;
}
/**
\brief Set software or hardware handshaking.
\param[in] addr pointer to dma register.
\return error code
*/
static int32_t ck_dma_set_handshaking(ck_dma_reg_t *addr, dma_handshaking_select_e handshaking)
{
uint32_t temp = addr->CHCTRLB;
temp &= 0xfffffeff;
temp |= (handshaking << 8);
addr->CHCTRLB = temp;
return 0;
}
static int ck_dma_assign_hdhs_interface(ck_dma_reg_t *addr, ckenum_dma_device_e device)
{
if (device < 0 || device >= CKENUM_DMA_MEMORY) {
return ERR_DMA(DRV_ERROR_PARAMETER);
}
addr->CHCTRLB &= 0xffffe1ff;
addr->CHCTRLB |= (device << 9);
return 0;
}
void ck_dma_irqhandler(int32_t idx)
{
ck_dma_priv_t *dma_priv = &dma_instance[idx];
ck_dma_reg_t *addr = (ck_dma_reg_t *)(dma_priv->base);
/*
* StatusInt_temp contain the information that which types of interrupr are
* requested.
*/
int32_t count = 0;
uint32_t temp = 0;
for (count = 0; count < dma_priv->ch_num; count++) {
addr = (ck_dma_reg_t *)(dma_priv->base + count * 0x30);
temp = addr->CHINTS;
if (temp != 0) {
break;
}
}
/* If Tfr interrupt is requested */
if (temp == CK_DMA_TFR) {
status[count] = DMA_STATE_DONE;
addr->CHINTC = temp;
if (dma_priv->cb_event) {
dma_priv->cb_event(count, DMA_EVENT_TRANSFER_DONE);
}
}
/* If Err interrput is requested */
if (temp == CK_DMA_ERR) {
status[count] = DMA_STATE_ERROR;
addr->CHINTC = temp;
if (dma_priv->cb_event) {
dma_priv->cb_event(count, DMA_EVENT_TRANSFER_ERROR);
}
}
}
/**
\brief Initialize DMA Interface. 1. Initializes the resources needed for the DMA interface 2.registers event callback function
\param[in] dmac idx
\return pointer to dma instances
*/
dmac_handle_t csi_dma_initialize(int32_t idx)
{
if (idx < 0 || idx >= CONFIG_DMAC_NUM) {
return NULL;
}
uint32_t base = 0u;
uint32_t irq = 0u;
int32_t real_idx = target_get_dmac(idx, &base, &irq);
if (real_idx != idx) {
return NULL;
}
ck_dma_priv_t *dma_priv = &dma_instance[idx];
dma_priv->base = base;
dma_priv->irq = irq;
dma_priv->ch_num = CK_DMA_MAXCHANNEL;
csi_vic_enable_irq(dma_priv->irq);
uint8_t count = 0u;
for (count = 0; count < dma_priv->ch_num; count++) {
ck_dma_reg_t *addr = (ck_dma_reg_t *)(dma_priv->base + count * 0x30);
addr->CHINTM = CK_DMA_MASK;
addr->CHINTC = CK_DMA_INTC;
}
return (dmac_handle_t)dma_priv;
}
/**
\brief De-initialize DMA Interface. stops operation and releases the software resources used by the interface
\param[in] handle damc handle to operate.
\return error code
*/
int32_t csi_dma_uninitialize(dmac_handle_t handle)
{
if (handle == NULL) {
return ERR_DMA(DRV_ERROR_PARAMETER);
}
ck_dma_priv_t *dma_priv = handle;
ck_dma_reg_t *addr = (ck_dma_reg_t *)(dma_priv->base);
uint8_t count;
for (count = 0; count < dma_priv->ch_num; count++) {
addr = (ck_dma_reg_t *)(dma_priv->base + count * 0x30);
addr->CHINTM = CK_DMA_MASK;
addr->CHINTC = CK_DMA_INTC;
}
csi_vic_disable_irq(dma_priv->irq);
return 0;
}
/**
\brief Get driver capabilities.
\param[in] idx dmac index.
\return \ref dma_capabilities_t
*/
dma_capabilities_t csi_dma_get_capabilities(int32_t idx)
{
if (idx > (CONFIG_DMAC_NUM - 1)) {
dma_capabilities_t ret;
memset(&ret, 0, sizeof(dma_capabilities_t));
return ret;
}
return dma_capabilities;
}
/**
\brief get one free dma channel
\param[in] handle damc handle to operate.
\param[in] ch channel num. if -1 then allocate a free channal in this dma
\return -1 - no channel can be used, other - channel index
*/
int32_t csi_dma_alloc_channel(dmac_handle_t handle, int32_t ch)
{
ck_dma_priv_t *dma_priv = handle;
if (handle == NULL || ch > dma_priv->ch_num) {
return ERR_DMA(DRV_ERROR_PARAMETER);
}
uint8_t ch_num = 0;
ck_dma_reg_t *addr = NULL;
if (ch == -1) { // alloc a free channal
for (ch_num = 0; ch_num < dma_priv->ch_num; ch_num++) {
addr = (ck_dma_reg_t *)(dma_priv->base + ch_num * 0x30);
if (ch_opened[ch_num] != 0x1) {
ch_opened[ch_num] = 1;
break;
}
}
if (ch_num >= dma_priv->ch_num) {
return -1;
}
} else { //alloc a fixed channel
addr = (ck_dma_reg_t *)(dma_priv->base + ch * 0x30);
if (ch_opened[ch] == 0x1) {
return ERR_DMA(DRV_ERROR_BUSY);
}
ch_opened[ch] = 1;
ch_num = ch;
}
addr->CHINTC = CK_DMA_INTC;
addr->CHINTM &= ~CK_DMA_MASK;
status[ch_num] = DMA_STATE_READY;
return ch_num;
}
/**
\brief release dma channel and related resources
\param[in] handle damc handle to operate.
\param[in] ch channel num.
\return error code
*/
int32_t csi_dma_release_channel(dmac_handle_t handle, int32_t ch)
{
ck_dma_priv_t *dma_priv = handle;
if (handle == NULL || ch >= dma_priv->ch_num || ch < 0) {
return ERR_DMA(DRV_ERROR_PARAMETER);
}
ck_dma_reg_t *addr = (ck_dma_reg_t *)(dma_priv->base + ch * 0x30);
status[ch] = DMA_STATE_FREE;
ch_opened[ch] = 0;
addr->CHINTC = CK_DMA_INTC;
addr->CHINTM = CK_DMA_MASK;
return 0;
}
/**
\brief
\param[in] handle damc handle to operate.
\param[in] ch channel num. if -1 then allocate a free channal in this dma
\param[in] psrcaddr dma transfer source address
\param[in] pdstaddr dma transfer destination address
\param[in] length dma transfer length
\param[in] config dma transfer configure
\param[in] cb_event Pointer to \ref dma_event_cb_t
\return error code if negative, otherwise return the channel num if success.
*/
int32_t csi_dma_config(dmac_handle_t handle, int32_t ch,
void *psrcaddr, void *pdstaddr,
uint32_t length, dma_config_t *config, dma_event_cb_t cb_event)
{
ck_dma_priv_t *dma_priv = handle;
if (handle == NULL || ch >= dma_priv->ch_num || config == NULL) {
return ERR_DMA(DRV_ERROR_PARAMETER);
}
if (ch == -1) { //alloc a free channel
ch = csi_dma_alloc_channel(handle, -1);
if (ch < 0) {
return ERR_DMA(DRV_ERROR_BUSY);
}
}
dma_priv->cb_event = cb_event;
ck_dma_reg_t *addr = (ck_dma_reg_t *)(dma_priv->base + ch * 0x30);
/* Initializes corresponding channel registers */
if ((length * config->src_tw) % config->dst_tw != 0) {
return ERR_DMA(DRV_ERROR_PARAMETER);
}
int32_t ret = ck_dma_set_transferwidth(addr, config->src_tw, config->dst_tw);
if (ret < 0) {
return ret;
}
int32_t grouplen = ((length * config->src_tw / config->dst_tw) - 1) % 16;
ck_dma_set_burstlength(addr, grouplen);
ret = ck_dma_set_transfertype(addr, config->type);
if (ret < 0) {
return ret;
}
if (config->type == DMA_MEM2MEM) {
ck_dma_set_handshaking(addr, DMA_HANDSHAKING_SOFTWARE);
ret = ck_dma_set_addrinc(addr , config->src_inc, config->dst_inc);
if (ret < 0) {
return ret;
}
} else if (config->type == DMA_MEM2PERH) {
ck_dma_set_handshaking(addr, DMA_HANDSHAKING_HARDWARE);
ret = ck_dma_set_addrinc(addr , config->src_inc, config->dst_inc);
if (ret < 0) {
return ret;
}
ret = ck_dma_assign_hdhs_interface(addr, config->hs_if);
if (ret < 0) {
return ret;
}
} else if (config->type == DMA_PERH2MEM) {
ck_dma_set_handshaking(addr, DMA_HANDSHAKING_HARDWARE);
ret = ck_dma_set_addrinc(addr , config->src_inc, config->dst_inc);
if (ret < 0) {
return ret;
}
ret = ck_dma_assign_hdhs_interface(addr, config->hs_if);
if (ret < 0) {
return ret;
}
}
ck_dma_set_channel(addr, (uint32_t)psrcaddr, (uint32_t)pdstaddr, length);
status[ch] = DMA_STATE_READY;
return ch;
}
/**
\brief start generate dma signal.
\param[in] handle damc handle to operate.
\param[in] ch channel num.
\return error code
*/
int32_t csi_dma_start(dmac_handle_t handle, int32_t ch)
{
ck_dma_priv_t *dma_priv = handle;
if (handle == NULL || ch >= dma_priv->ch_num || ch < 0) {
return ERR_DMA(DRV_ERROR_PARAMETER);
}
status[ch] = DMA_STATE_BUSY;
ck_dma_reg_t *addr = (ck_dma_reg_t *)(dma_priv->base + ch * 0x30);
addr->CHCTRLB |= CK_DMA_INT_EN; // interrupt enable
addr->CHEN |= CK_DMA_CH_EN;
return 0;
}
/**
\brief Stop generate dma signal.
\param[in] handle damc handle to operate.
\param[in] ch channel num.
\return error code
*/
int32_t csi_dma_stop(dmac_handle_t handle, int32_t ch)
{
if (handle == NULL) {
return ERR_DMA(DRV_ERROR_PARAMETER);
}
ck_dma_priv_t *dma_priv = handle;
if (ch >= dma_priv->ch_num || ch < 0) {
return ERR_DMA(DRV_ERROR_PARAMETER);
}
status[ch] = DMA_STATE_DONE;
ck_dma_reg_t *addr = (ck_dma_reg_t *)(dma_priv->base + ch * 0x30);
addr->CHCTRLB &= ~CK_DMA_INT_EN; // interrupt disable
addr->CHEN &= ~CK_DMA_CH_EN;
return 0;
}
/**
\brief Get DMA status.
\param[in] handle damc handle to operate.
\param[in] ch channel num.
\return DMA status \ref dma_status_t
*/
dma_status_e csi_dma_get_status(dmac_handle_t handle, int32_t ch)
{
if (handle == NULL) {
return ERR_DMA(DRV_ERROR_PARAMETER);
}
ck_dma_priv_t *dma_priv = handle;
if (ch >= dma_priv->ch_num || ch < 0) {
return ERR_DMA(DRV_ERROR_PARAMETER);
}
return status[ch];
}

View file

@ -0,0 +1,613 @@
/*
* Copyright (C) 2017 C-SKY Microsystems Co., Ltd. All rights reserved.
*
* 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 ck_dmac_v2.c
* @brief CSI Source File for DMAC Driver
* @version V1.0
* @date 02. June 2017
******************************************************************************/
#include <csi_config.h>
#include <soc.h>
#include <stdbool.h>
#include <ck_dmac_v2.h>
#include <csi_core.h>
#include <drv_dmac.h>
#include <string.h>
#define ERR_DMA(errno) (CSI_DRV_ERRNO_DMA_BASE | errno)
typedef struct {
uint32_t base;
uint32_t irq;
dma_event_cb_t cb_event;
uint8_t ch_num;
dma_channel_req_mode_e ch_mode;
} ck_dma_priv_t;
extern int32_t target_get_dmac(int32_t idx, uint32_t *base, uint32_t *irq);
extern int32_t target_get_dmac_count(void);
static ck_dma_priv_t dma_instance[CONFIG_DMAC_NUM];
static const dma_capabilities_t dma_capabilities = {
.unalign_addr = 1, ///< support for unalign address transfer when memory is source
};
static volatile dma_status_e status[CK_DMA_MAXCHANNEL] = {DMA_STATE_FREE, DMA_STATE_FREE};
static volatile uint8_t ch_opened[CK_DMA_MAXCHANNEL] = {0, 0};
static int32_t ck_dma_set_total_size(ck_dma_reg_t *addr, uint32_t len)
{
addr->CHCTRLA &= 0xff000fff;
addr->CHCTRLA |= (len - 1) << 12;
return 0;
}
static int32_t ck_dma_set_channel(ck_dma_reg_t *addr, uint32_t source, uint32_t dest)
{
addr->SAR = source;
addr->DAR = dest ;
return 0;
}
static int32_t ck_dma_set_addrinc(ck_dma_reg_t *addr, enum_addr_state_e src_addrinc, enum_addr_state_e dst_addrinc)
{
if ((src_addrinc != DMA_ADDR_INCREMENT && src_addrinc != DMA_ADDR_DECREMENT && src_addrinc != DMA_ADDR_NOCHANGE) ||
(dst_addrinc != DMA_ADDR_INCREMENT && dst_addrinc != DMA_ADDR_DECREMENT && dst_addrinc != DMA_ADDR_NOCHANGE)) {
return ERR_DMA(DRV_ERROR_PARAMETER);
}
uint32_t temp = addr->CHCTRLA;
temp &= 0xffffff0f;
temp |= (src_addrinc << 6);
temp |= (dst_addrinc << 4);
addr->CHCTRLA = temp;
return 0;
}
int32_t ck_dma_set_transferwidth(ck_dma_reg_t *addr, dma_datawidth_e src_width, dma_datawidth_e dst_width)
{
if ((src_width != DMA_DATAWIDTH_SIZE8 && src_width != DMA_DATAWIDTH_SIZE16 && src_width != DMA_DATAWIDTH_SIZE32) ||
(dst_width != DMA_DATAWIDTH_SIZE8 && dst_width != DMA_DATAWIDTH_SIZE16 && dst_width != DMA_DATAWIDTH_SIZE32)) {
return ERR_DMA(DRV_ERROR_PARAMETER);
}
uint32_t temp = addr->CHCTRLA;
temp &= 0xfffffff0;
temp |= (src_width - 1) << 2;
temp |= (dst_width -1);
addr->CHCTRLA = temp;
return 0;
}
static int32_t ck_dma_trans_mode_set(ck_dma_reg_t *addr, dma_trig_trans_mode_e mode)
{
addr->CHCTRLB &= 0xfffffff9;
addr->CHCTRLB |= (mode << 1);
return 0;
}
static int32_t ck_dma_set_addr_endian(ck_dma_reg_t *addr, dma_addr_endian_e src_endian, dma_addr_endian_e dst_endian)
{
addr->CHCTRLB &= 0xffff9fff;
addr->CHCTRLB |= (src_endian << 13);
addr->CHCTRLB |= (dst_endian << 14);
return 0;
}
static int32_t ck_dma_set_singlemode(ck_dma_reg_t *addr, dma_config_t *config)
{
addr->CHCTRLA &= 0xefffffff;
addr->CHCTRLA |= (config->single_dir << 26);
if (config->preemption == 0) {
if (config->single_dir == SOURCE) {
addr->CHCTRLA &= 0xfbffffff;
} else {
addr->CHCTRLA &= 0xfdffffff;
}
} else if (config->preemption == 1) {
if (config->single_dir == DEST) {
addr->CHCTRLA |= 0x04000000;
} else {
addr->CHCTRLA |= 0x02000000;
}
} else {
return ERR_DMA(DRV_ERROR_PARAMETER);
}
return 0;
}
static int32_t ck_dma_set_groupmode(ck_dma_reg_t *addr, dma_config_t *config)
{
if (config->src_inc == DMA_ADDR_INC || config->src_inc == DMA_ADDR_DEC) {
addr->CHCTRLA &= 0xdfffffff;
} else if (config->src_inc == DMA_ADDR_CONSTANT) {
addr->CHCTRLA |= (1 << 29);
} else {
return ERR_DMA(DRV_ERROR_PARAMETER);
}
if (config->dst_inc == DMA_ADDR_INC || config->dst_inc == DMA_ADDR_DEC) {
addr->CHCTRLA &= 0x7fffffff;
} else if (config->dst_inc == DMA_ADDR_CONSTANT) {
addr->CHCTRLA |= (1 << 31);
} else {
return ERR_DMA(DRV_ERROR_PARAMETER);
}
if (config->preemption == 0) {
addr->CHCTRLA &= 0xfeffffff;
} else if (config->preemption == 1) {
//Channel interrupt by high priority channel mode Control
addr->CHCTRLA |= (1 << 24);
} else {
return ERR_DMA(DRV_ERROR_PARAMETER);
}
addr->CHCTRLA &= 0xfffff0ff;
addr->CHCTRLA |= ((config->group_len - 1) << 8);
return 0;
}
static int32_t ck_dma_set_blockmode(ck_dma_reg_t *addr)
{
return 0;
}
void ck_dma_irqhandler(int32_t idx)
{
ck_dma_priv_t *dma_priv = &dma_instance[idx];
ck_dma_reg_t *addr = (ck_dma_reg_t *)(dma_priv->base);
/*
* StatusInt_temp contain the information that which types of interrupr are
* requested.
*/
uint32_t count = 0;
uint32_t temp = 0;
uint32_t val_dma_chints;
uint32_t reg;
for (count = 0; count < dma_priv->ch_num; count++) {
addr = (ck_dma_reg_t *)(dma_priv->base + count * 0x30);
reg = dma_priv->base + count * 0x30;
val_dma_chints = *(volatile uint32_t *)(reg + 0x14);
if (val_dma_chints != 0) {
addr->CHINTC = 0xf;
break;
}
}
temp = val_dma_chints;
/* dma transfer complete */
if (temp & CK_DMA_TFR) {
status[count] = DMA_STATE_DONE;
if (dma_priv->cb_event) {
dma_priv->cb_event(count, DMA_EVENT_TRANSFER_DONE);
}
}
/* dam transfer half done*/
if (temp & CK_DMA_HTFR) {
if (dma_priv->cb_event) {
dma_priv->cb_event(count, DMA_EVENT_TRANSFER_HALF_DONE);
}
}
/* transfer complete in a certain dma trigger mode */
if (temp & CK_DMA_TRGETCMPFR) {
if (dma_priv->cb_event) {
dma_priv->cb_event(count, DMA_EVENT_TRANSFER_MODE_DONE);
}
}
/* transfer error */
if (temp & CK_DMA_ERR) {
status[count] = DMA_STATE_ERROR;
if (dma_priv->cb_event) {
dma_priv->cb_event(count, DMA_EVENT_TRANSFER_ERROR);
}
}
uint32_t i;
temp = *(uint32_t *)CK_V2_DMAC_STATUSCHPEND;
for (i = 0; i < dma_priv->ch_num; i++) {
if ((1 << i) & temp) {
if (dma_priv->cb_event) {
dma_priv->cb_event(i, DMA_EVENT_CAHNNEL_PEND);
}
break;
}
}
}
/**
\brief Initialize DMA Interface. 1. Initializes the resources needed for the DMA interface 2.registers event callback function
\param[in] dmac idx
\return pointer to dma instances
*/
dmac_handle_t csi_dma_initialize(int32_t idx)
{
if (idx < 0 || idx >= CONFIG_DMAC_NUM) {
return NULL;
}
uint32_t base = 0u;
uint32_t irq = 0u;
int32_t real_idx = target_get_dmac(idx, &base, &irq);
if (real_idx != idx) {
return NULL;
}
ck_dma_priv_t *dma_priv = &dma_instance[idx];
dma_priv->base = base;
dma_priv->irq = irq;
dma_priv->ch_num = CK_DMA_MAXCHANNEL;
csi_vic_enable_irq(dma_priv->irq);
uint8_t count = 0u;
for (count = 0; count < dma_priv->ch_num; count++) {
ck_dma_reg_t *addr = (ck_dma_reg_t *)(dma_priv->base + count * 0x30);
addr->CHINTM |= ~CK_DMA_MASK;
addr->CHINTC |= CK_DMA_INTC;
}
*(volatile uint32_t *)CK_V2_DMAC_STATUSCHPEND = CK_DMA_ALL_CAHNNELS_PEND_INTR_VALID;
*(volatile uint32_t *)CK_V2_DMAC_CHSR = CK_DMA_ALL_CAHNNELS_DATA_TRANS_BUSY_VALID;
return (dmac_handle_t)dma_priv;
}
/**
\brief De-initialize DMA Interface. stops operation and releases the software resources used by the interface
\param[in] handle damc handle to operate.
\return error code
*/
int32_t csi_dma_uninitialize(dmac_handle_t handle)
{
if (handle == NULL) {
return ERR_DMA(DRV_ERROR_PARAMETER);
}
ck_dma_priv_t *dma_priv = handle;
ck_dma_reg_t *addr = (ck_dma_reg_t *)(dma_priv->base);
uint8_t count;
for (count = 0; count < dma_priv->ch_num; count++) {
addr = (ck_dma_reg_t *)(dma_priv->base + count * 0x30);
addr->CHINTM = CK_CHINTM_RESETVALUE;
addr->CHINTC = CK_CHINTC_RESETVALUE;
}
csi_vic_disable_irq(dma_priv->irq);
return 0;
}
/**
\brief Get driver capabilities.
\param[in] idx dmac index.
\return \ref dma_capabilities_t
*/
dma_capabilities_t csi_dma_get_capabilities(int32_t idx)
{
if (idx > (CONFIG_DMAC_NUM - 1)) {
dma_capabilities_t ret;
memset(&ret, 0, sizeof(dma_capabilities_t));
return ret;
}
return dma_capabilities;
}
/**
\brief get one free dma channel
\param[in] handle damc handle to operate.
\param[in] ch channel num. if -1 then allocate a free channal in this dma
\return -1 - no channel can be used, other - channel index
*/
int32_t csi_dma_alloc_channel(dmac_handle_t handle, int32_t ch)
{
ck_dma_priv_t *dma_priv = handle;
if (handle == NULL || ch > dma_priv->ch_num) {
return ERR_DMA(DRV_ERROR_PARAMETER);
}
uint8_t ch_num = 0;
ck_dma_reg_t *addr = NULL;
if (ch == -1) { // alloc a free channal
for (ch_num = 0; ch_num < dma_priv->ch_num; ch_num++) {
addr = (ck_dma_reg_t *)(dma_priv->base + ch_num * 0x30);
if (ch_opened[ch_num] != 0x1) {
ch_opened[ch_num] = 1;
break;
}
}
if (ch_num >= dma_priv->ch_num) {
return -1;
}
} else { //alloc a fixed channel
addr = (ck_dma_reg_t *)(dma_priv->base + ch * 0x30);
if (ch_opened[ch] == 0x1) {
return ERR_DMA(DRV_ERROR_BUSY);
}
ch_opened[ch] = 1;
ch_num = ch;
}
addr->CHINTM |= ~CK_DMA_MASK;
addr->CHINTC |= CK_DMA_INTC;
status[ch_num] = DMA_STATE_READY;
return ch_num;
}
/**
\brief release dma channel and related resources
\param[in] handle damc handle to operate.
\param[in] ch channel num.
\return error code
*/
int32_t csi_dma_release_channel(dmac_handle_t handle, int32_t ch)
{
ck_dma_priv_t *dma_priv = handle;
if (handle == NULL || ch >= dma_priv->ch_num || ch < 0) {
return ERR_DMA(DRV_ERROR_PARAMETER);
}
ck_dma_reg_t *addr = (ck_dma_reg_t *)(dma_priv->base + ch * 0x30);
status[ch] = DMA_STATE_FREE;
ch_opened[ch] = 0;
addr->CHINTM = CK_CHINTM_RESETVALUE;
addr->CHINTC = CK_CHINTC_RESETVALUE;
return 0;
}
/**
\brief
\param[in] handle damc handle to operate.
\param[in] ch channel num. if -1 then allocate a free channal in this dma
\param[in] psrcaddr dma transfer source address
\param[in] pstdaddr dma transfer dest address
\param[in] length dma transfer length
\param[in] config dma transfer configure
\param[in] cb_event Pointer to \ref dma_event_cb_t
\return error code
*/
int32_t csi_dma_config(dmac_handle_t handle, int32_t ch,
void *psrcaddr, void *pstdaddr,
uint32_t length, dma_config_t *config, dma_event_cb_t cb_event)
{
ck_dma_priv_t *dma_priv = handle;
uint32_t src_in_bytes;
uint32_t dst_in_bytes;
int32_t ret;
if (handle == NULL || ch >= dma_priv->ch_num || config == NULL) {
return ERR_DMA(DRV_ERROR_PARAMETER);
}
if (!(config->src_tw) || !(config->dst_tw)) {
return ERR_DMA(DRV_ERROR_PARAMETER);
}
src_in_bytes = config->src_tw ;
dst_in_bytes = config->dst_tw ;
if (config->mode == GROUP_TRIGGER || config->mode == BLOCK_TRIGGER) {
if ((length % src_in_bytes != 0) || (length % dst_in_bytes != 0)) {
return ERR_DMA(DRV_ERROR_PARAMETER);
}
}
if ((length * config->src_tw) % config->dst_tw != 0) {
return ERR_DMA(DRV_ERROR_PARAMETER);
}
if (ch == -1) { //alloc a free channel
ch = csi_dma_alloc_channel(handle, -1);
if (ch < 0) {
return ERR_DMA(DRV_ERROR_BUSY);
}
}
dma_priv->cb_event = cb_event;
dma_priv->ch_mode = config->ch_mode;
ck_dma_reg_t *addr = (ck_dma_reg_t *)(dma_priv->base + ch * 0x30);
/* Initializes corresponding channel registers */
ret = ck_dma_set_total_size(addr, length);
if (ret < 0) {
return ret;
}
ret = ck_dma_set_transferwidth(addr, config->src_tw, config->dst_tw);
if (ret < 0) {
return ret;
}
ret = ck_dma_set_addrinc(addr , config->src_inc, config->dst_inc);
if (ret < 0) {
return ret;
}
ret = ck_dma_set_addr_endian(addr, config->src_endian, config->dst_endian);
if (ret < 0) {
return ret;
}
ret = ck_dma_trans_mode_set(addr, config->mode);
if (ret < 0) {
return ret;
}
if (config->mode == SINGLE_TRIGGER) {
ret = ck_dma_set_singlemode(addr, config);
if (ret < 0) {
return ret;
}
} else if (config->mode == GROUP_TRIGGER) {
if ((config->group_len != DMA_GROUP_LEN1) && (config->group_len != DMA_GROUP_LEN2) && (config->group_len != DMA_GROUP_LEN3) && (config->group_len != DMA_GROUP_LEN4) && (config->group_len != DMA_GROUP_LEN5) && (config->group_len != DMA_GROUP_LEN6) && (config->group_len != DMA_GROUP_LEN7) && (config->group_len != DMA_GROUP_LEN8)) {
return ERR_DMA(DRV_ERROR_PARAMETER);;
}
if ((config->group_len % src_in_bytes != 0) || (config->group_len % dst_in_bytes != 0)) {
return ERR_DMA(DRV_ERROR_PARAMETER);
}
ret = ck_dma_set_groupmode(addr, config);
if (ret < 0) {
return ret;
}
} else if (config->mode == BLOCK_TRIGGER) {
ret =ck_dma_set_blockmode(addr);
if (ret < 0) {
return ret;
}
} else {
return ERR_DMA(DRV_ERROR_PARAMETER);
}
ret = ck_dma_set_channel(addr, (uint32_t)psrcaddr, (uint32_t)pstdaddr);
if (ret < 0) {
return ret;
}
status[ch] = DMA_STATE_READY;
return 0;
}
/**
\brief start generate dma signal.
\param[in] handle damc handle to operate.
\param[in] ch channel num.
\return error code
*/
int32_t csi_dma_start(dmac_handle_t handle, int32_t ch)
{
ck_dma_priv_t *dma_priv = handle;
if (handle == NULL || ch >= dma_priv->ch_num || ch < 0) {
return ERR_DMA(DRV_ERROR_PARAMETER);
}
ck_dma_reg_t *addr = (ck_dma_reg_t *)(dma_priv->base + ch * 0x30);
addr->CHCTRLB |= CK_DMA_INT_EN;
//global register DMACCFG : the global DMAC enable bit only can be operated in security wolrd.
//already do in startup.S
//*(volatile uint32_t *)CK_V2_DMAC_DMACCFG = CK_DMACCFG_EN;
addr->CHEN |= CK_DMA_CH_EN;
if (dma_priv->ch_mode == SOFTWARE) {
addr->CHSREQ = CK_DMA_CH_REQ;
}
status[ch] = DMA_STATE_BUSY;
return 0;
}
/**
\brief Stop generate dma signal.
\param[in] handle damc handle to operate.
\param[in] ch channel num.
\return error code
*/
int32_t csi_dma_stop(dmac_handle_t handle, int32_t ch)
{
if (handle == NULL) {
return ERR_DMA(DRV_ERROR_PARAMETER);
}
ck_dma_priv_t *dma_priv = handle;
if (ch >= dma_priv->ch_num || ch < 0) {
return ERR_DMA(DRV_ERROR_PARAMETER);
}
ck_dma_reg_t *addr = (ck_dma_reg_t *)(dma_priv->base + ch * 0x30);
addr->CHCTRLB &= ~CK_DMA_INT_EN; // interrupt disable
addr->CHEN &= ~CK_DMA_CH_EN;
if (dma_priv->ch_mode == SOFTWARE) {
addr->CHSREQ = 0;
}
status[ch] = DMA_STATE_DONE;
return 0;
}
/**
\brief Get DMA status.
\param[in] handle damc handle to operate.
\param[in] ch channel num.
\return DMA status \ref dma_status_t
*/
dma_status_e csi_dma_get_status(dmac_handle_t handle, int32_t ch)
{
if (handle == NULL) {
return ERR_DMA(DRV_ERROR_PARAMETER);
}
ck_dma_priv_t *dma_priv = handle;
if (ch >= dma_priv->ch_num || ch < 0) {
return ERR_DMA(DRV_ERROR_PARAMETER);
}
uint32_t tmp = *(uint32_t *)CK_V2_DMAC_CHSR;
if ((1 << ch) & tmp) {
if (status[ch] != DMA_STATE_BUSY) {
status[ch] = DMA_STATE_BUSY;
}
}
return status[ch];
}

View file

@ -0,0 +1,563 @@
/*
* Copyright (C) 2017 C-SKY Microsystems Co., Ltd. All rights reserved.
*
* 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 dw_dmac.c
* @brief CSI Source File for DMAC Driver
* @version V1.0
* @date 02. June 2017
******************************************************************************/
#include <stdbool.h>
#include <csi_config.h>
#include "dw_dmac.h"
#include "csi_core.h"
#include "drv_dmac.h"
#include "soc.h"
#include <string.h>
#define ERR_DMA(errno) (CSI_DRV_ERRNO_DMA_BASE | errno)
typedef struct {
uint32_t base;
uint32_t control_base;
uint32_t irq;
dma_event_cb_t cb_event;
uint8_t ch_num;
uint8_t ch_opened[CK_DMA_MAXCHANNEL];
dma_status_e status[CK_DMA_MAXCHANNEL];
} dw_dma_priv_t;
static dw_dma_priv_t dma_instance[CONFIG_DMAC_NUM];
static const dma_capabilities_t dma_capabilities = {
.unalign_addr = 1, ///< support for unalign address transfer when memory is source
};
#define readl(addr) \
*((volatile uint32_t *)(addr))
#define writel(b, addr) \
*((volatile uint32_t *)(addr)) = b
static int32_t dw_dma_set_channel(uint32_t addr, uint8_t ch, uint32_t source, uint32_t dest, uint32_t size)
{
writel(size, addr + ch*0x58 + DMA_REG_CTRLbx);
writel(source, addr + ch*0x58 + DMA_REG_SARx);
writel(dest, addr + ch*0x58 + DMA_REG_DARx);
return 0;
}
static int32_t dw_dma_set_transfertype(uint32_t addr, uint8_t ch, dma_trans_type_e transtype)
{
if (transtype >= DMA_PERH2PERH) {
return ERR_DMA(DRV_ERROR_PARAMETER);
}
uint32_t value = readl(addr + ch*0x58 + DMA_REG_CTRLax);
value &= ~(0x300000);
value |= transtype << 20;
writel(value, addr + ch*0x58 + DMA_REG_CTRLax);
return 0;
}
static int32_t dw_dma_set_addrinc(uint32_t addr, uint8_t ch, enum_addr_state_e src_addrinc, enum_addr_state_e dst_addrinc)
{
if ((src_addrinc != DMA_ADDR_INCREMENT && src_addrinc != DMA_ADDR_DECREMENT && src_addrinc != DMA_ADDR_NOCHANGE) ||
(dst_addrinc != DMA_ADDR_INCREMENT && dst_addrinc != DMA_ADDR_DECREMENT && dst_addrinc != DMA_ADDR_NOCHANGE)) {
return ERR_DMA(DRV_ERROR_PARAMETER);
}
uint32_t value = readl(addr + ch*0x58 + DMA_REG_CTRLax);
value &= ~(0x780);
value |= (src_addrinc << 9);
value |= (dst_addrinc << 7);
writel(value, addr + ch*0x58 + DMA_REG_CTRLax);
return 0;
}
static int32_t dw_dma_set_transferwidth(uint32_t addr, uint8_t ch, dma_datawidth_e src_width, dma_datawidth_e dst_width)
{
if ((src_width != DMA_DATAWIDTH_SIZE8 && src_width != DMA_DATAWIDTH_SIZE16 && src_width != DMA_DATAWIDTH_SIZE32) ||
(dst_width != DMA_DATAWIDTH_SIZE8 && dst_width != DMA_DATAWIDTH_SIZE16 && dst_width != DMA_DATAWIDTH_SIZE32)) {
return ERR_DMA(DRV_ERROR_PARAMETER);
}
uint32_t value = readl(addr + ch*0x58 + DMA_REG_CTRLax);
value &= ~(0x7e);
if (src_width == DMA_DATAWIDTH_SIZE32) {
value |= (src_width - 2) << 4;
} else {
value |= (src_width - 1) << 4;
}
if (dst_width == DMA_DATAWIDTH_SIZE32) {
value |= (dst_width - 2) << 1;
} else {
value |= (dst_width - 1) << 1;
}
writel(value, addr + ch*0x58 + DMA_REG_CTRLax);
return 0;
}
static int32_t dw_dma_set_burstlength(uint32_t addr, uint8_t ch, uint8_t burstlength)
{
uint32_t value = readl(addr + ch*0x58 + DMA_REG_CTRLax);
value &= ~(0x1f800);
value |= burstlength << 11 | burstlength << 14;
writel(value, addr + ch*0x58 + DMA_REG_CTRLax);
return 0;
}
/**
\brief Set software or hardware handshaking.
\param[in] addr pointer to dma register.
\return error code
*/
static int32_t dw_dma_set_handshaking(uint32_t addr, uint8_t ch, dma_handshaking_select_e src_handshaking, dma_handshaking_select_e dst_handshaking)
{
uint32_t value = readl(addr + ch*0x58 + DMA_REG_CFGax);
value &= ~(0xc00);
value |= (src_handshaking << 11 | dst_handshaking << 10);
writel(value, addr + ch*0x58 + DMA_REG_CFGax);
return 0;
}
static int dw_dma_assign_hdhs_interface(uint32_t addr, uint8_t ch, dwenum_dma_device_e src_device, dwenum_dma_device_e dst_device)
{
if (src_device < 0 || src_device >= DWENUM_DMA_MEMORY || dst_device < 0 || dst_device >= DWENUM_DMA_MEMORY) {
return ERR_DMA(DRV_ERROR_PARAMETER);
}
uint32_t value = readl(addr + ch*0x58 + DMA_REG_CFGbx);
value &= ~(0x7f80);
value |= (src_device << 7 | dst_device << 11);
writel(value, addr + ch*0x58 + DMA_REG_CFGbx);
return 0;
}
void dw_dmac_irqhandler(int32_t idx)
{
dw_dma_priv_t *dma_priv = &dma_instance[idx];
uint32_t addr = dma_priv->base;
/*
* StatusInt_temp contain the information that which types of interrupr are
* requested.
*/
int32_t count = 0;
uint32_t temp = 0;
temp = readl(addr + DMA_REG_StatusTfr);
if (temp) {
for (count = 0; count < dma_priv->ch_num; count++) {
if(temp == (1 << count)) {
break;
}
}
dma_priv->status[count] = DMA_STATE_DONE;
writel(temp, addr + DMA_REG_ClearTfr);
if (dma_priv->cb_event) {
dma_priv->cb_event(count, DMA_EVENT_TRANSFER_DONE);
}
return;
}
temp = readl(addr + DMA_REG_StatusErr);
if (temp) {
for (count = 0; count < dma_priv->ch_num; count++) {
if(temp == (1 << count)) {
break;
}
}
dma_priv->status[count] = DMA_STATE_ERROR;
writel(temp, addr + DMA_REG_ClearTfr);
if (dma_priv->cb_event) {
dma_priv->cb_event(count, DMA_EVENT_TRANSFER_ERROR);
}
return;
}
}
int32_t __attribute__((weak)) target_get_dmac(uint32_t idx, uint32_t *base, uint32_t *irq)
{
return NULL;
}
/**
\brief Initialize DMA Interface. 1. Initializes the resources needed for the DMA interface 2.registers event callbadw function
\param[in] dmac idx
\return pointer to dma instances
*/
dmac_handle_t csi_dma_initialize(int32_t idx)
{
if (idx < 0 || idx >= CONFIG_DMAC_NUM) {
return NULL;
}
uint32_t base = 0u;
uint32_t irq = 0u;
int32_t real_idx = target_get_dmac(idx, &base, &irq);
if (real_idx != idx) {
return NULL;
}
dw_dma_priv_t *dma_priv = &dma_instance[idx];
dma_priv->base = base;
dma_priv->irq = irq;
dma_priv->ch_num = CK_DMA_MAXCHANNEL;
csi_vic_enable_irq(dma_priv->irq);
writel(CK_DMA_MASK, base + DMA_REG_MaskTfr);
writel(CK_DMA_MASK, base + DMA_REG_MaskErr);
writel(CK_DMA_MASK, base + DMA_REG_MaskBlock);
writel(CK_DMA_MASK, base + DMA_REG_MaskSrcTran);
writel(CK_DMA_MASK, base + DMA_REG_MaskDstTran);
writel(CK_DMA_INTC, base + DMA_REG_ClearTfr);
writel(CK_DMA_INTC, base + DMA_REG_ClearBlock);
writel(CK_DMA_INTC, base + DMA_REG_ClearErr);
writel(CK_DMA_INTC, base + DMA_REG_ClearSrcTran);
writel(CK_DMA_INTC, base + DMA_REG_ClearDstTran);
return (dmac_handle_t)dma_priv;
}
/**
\brief De-initialize DMA Interface. stops operation and releases the software resources used by the interface
\param[in] handle damc handle to operate.
\return error code
*/
int32_t csi_dma_uninitialize(dmac_handle_t handle)
{
if (handle == NULL) {
return ERR_DMA(DRV_ERROR_PARAMETER);
}
dw_dma_priv_t *dma_priv = handle;
uint32_t addr = dma_priv->base;
writel(CK_DMA_MASK, addr + DMA_REG_MaskTfr);
writel(CK_DMA_MASK, addr + DMA_REG_MaskErr);
writel(CK_DMA_MASK, addr + DMA_REG_MaskBlock);
writel(CK_DMA_MASK, addr + DMA_REG_MaskSrcTran);
writel(CK_DMA_MASK, addr + DMA_REG_MaskDstTran);
writel(CK_DMA_INTC, addr + DMA_REG_ClearTfr);
writel(CK_DMA_INTC, addr + DMA_REG_ClearBlock);
writel(CK_DMA_INTC, addr + DMA_REG_ClearErr);
writel(CK_DMA_INTC, addr + DMA_REG_ClearSrcTran);
writel(CK_DMA_INTC, addr + DMA_REG_ClearDstTran);
csi_vic_disable_irq(dma_priv->irq);
return 0;
}
/**
\brief Get driver capabilities.
\param[in] idx dmac index.
\return \ref dma_capabilities_t
*/
dma_capabilities_t csi_dma_get_capabilities(int32_t idx)
{
if (idx > (CONFIG_DMAC_NUM - 1)) {
dma_capabilities_t ret;
memset(&ret, 0, sizeof(dma_capabilities_t));
return ret;
}
return dma_capabilities;
}
/**
\brief get one free dma channel
\param[in] handle damc handle to operate.
\param[in] ch channel num. if -1 then allocate a free channal in this dma
\return -1 - no channel can be used, other - channel index
*/
int32_t csi_dma_alloc_channel(dmac_handle_t handle, int32_t ch)
{
dw_dma_priv_t *dma_priv = handle;
if (handle == NULL || ch > dma_priv->ch_num) {
return ERR_DMA(DRV_ERROR_PARAMETER);
}
uint8_t ch_num = 0;
if (ch == -1) { // alloc a free channal
for (ch_num = 0; ch_num < dma_priv->ch_num; ch_num++) {
if (dma_priv->ch_opened[ch_num] != 0x1) {
dma_priv->ch_opened[ch_num] = 1;
break;
}
}
if (ch_num >= dma_priv->ch_num) {
return -1;
}
} else { //alloc a fixed channel
if (dma_priv->ch_opened[ch] == 0x1) {
return ERR_DMA(DRV_ERROR_BUSY);
}
dma_priv->ch_opened[ch] = 1;
ch_num = ch;
}
uint32_t addr = dma_priv->base;
writel((1 << ch_num), addr + DMA_REG_ClearTfr);
writel((1 << ch_num), addr + DMA_REG_ClearBlock);
writel((1 << ch_num), addr + DMA_REG_ClearErr);
writel((1 << ch_num), addr + DMA_REG_ClearSrcTran);
writel((1 << ch_num), addr + DMA_REG_ClearDstTran);
uint32_t value = 1 << ch_num | (1 << (ch_num+8));
writel(value, addr + DMA_REG_MaskTfr);
writel(value, addr + DMA_REG_MaskErr);
dma_priv->status[ch_num] = DMA_STATE_READY;
return ch_num;
}
/**
\brief release dma channel and related resources
\param[in] handle damc handle to operate.
\param[in] ch channel num.
\return error code
*/
int32_t csi_dma_release_channel(dmac_handle_t handle, int32_t ch)
{
dw_dma_priv_t *dma_priv = handle;
if (handle == NULL || ch >= dma_priv->ch_num || ch < 0) {
return ERR_DMA(DRV_ERROR_PARAMETER);
}
uint32_t addr = dma_priv->base;
dma_priv->status[ch] = DMA_STATE_FREE;
dma_priv->ch_opened[ch] = 0;
writel((1 << ch), addr + DMA_REG_ClearTfr);
writel((1 << ch), addr + DMA_REG_ClearBlock);
writel((1 << ch), addr + DMA_REG_ClearErr);
writel((1 << ch), addr + DMA_REG_ClearSrcTran);
writel((1 << ch), addr + DMA_REG_ClearDstTran);
uint32_t value = (1 << (ch+8));
writel(value, addr + DMA_REG_MaskTfr);
writel(value, addr + DMA_REG_MaskErr);
return 0;
}
/**
\brief
\param[in] handle damc handle to operate.
\param[in] ch channel num. if -1 then allocate a free channal in this dma
\param[in] psrcaddr dma transfer source address
\param[in] pdstaddr dma transfer destination address
\param[in] length dma transfer length
\param[in] config dma transfer configure
\param[in] cb_event Pointer to \ref dma_event_cb_t
\return error code
*/
int32_t csi_dma_config(dmac_handle_t handle, int32_t ch,
void *psrcaddr, void *pdstaddr,
uint32_t length, dma_config_t *config, dma_event_cb_t cb_event)
{
dw_dma_priv_t *dma_priv = handle;
if (handle == NULL || ch >= dma_priv->ch_num || config == NULL) {
return ERR_DMA(DRV_ERROR_PARAMETER);
}
if (ch == -1) { //alloc a free channel
ch = csi_dma_alloc_channel(handle, -1);
if (ch < 0) {
return ERR_DMA(DRV_ERROR_BUSY);
}
}
dma_priv->cb_event = cb_event;
uint32_t addr = dma_priv->base;
/* Initializes corresponding channel registers */
if ((length * config->src_tw) % config->dst_tw != 0) {
return ERR_DMA(DRV_ERROR_PARAMETER);
}
int32_t ret = dw_dma_set_transferwidth(addr, ch, config->src_tw, config->dst_tw);
if (ret < 0) {
return ret;
}
// int32_t grouplen = ((length * config->src_tw / config->dst_tw) - 1) % 16;
uint8_t i;
for (i = 7; i > 0; i--) {
if (!((length * config->src_tw / config->dst_tw) % (2 << (i + 1)))) {
break;
}
}
int32_t grouplen = i;
if (i == 0) {
grouplen = 0;
}
dw_dma_set_burstlength(addr, ch, grouplen);
ret = dw_dma_set_transfertype(addr, ch, config->type);
if (ret < 0) {
return ret;
}
if (config->type == DMA_MEM2MEM) {
dw_dma_set_handshaking(addr, ch, DMA_HANDSHAKING_SOFTWARE, DMA_HANDSHAKING_SOFTWARE);
ret = dw_dma_set_addrinc(addr, ch, config->src_inc, config->dst_inc);
if (ret < 0) {
return ret;
}
} else if (config->type == DMA_MEM2PERH) {
dw_dma_set_handshaking(addr, ch, DMA_HANDSHAKING_SOFTWARE, DMA_HANDSHAKING_HARDWARE);
ret = dw_dma_set_addrinc(addr, ch, config->src_inc, config->dst_inc);
if (ret < 0) {
return ret;
}
ret = dw_dma_assign_hdhs_interface(addr, ch, config->hs_if, config->hs_if);
if (ret < 0) {
return ret;
}
} else if (config->type == DMA_PERH2MEM) {
dw_dma_set_handshaking(addr, ch, DMA_HANDSHAKING_HARDWARE, DMA_HANDSHAKING_SOFTWARE);
ret = dw_dma_set_addrinc(addr, ch, config->src_inc, config->dst_inc);
if (ret < 0) {
return ret;
}
ret = dw_dma_assign_hdhs_interface(addr, ch, config->hs_if, config->hs_if);
if (ret < 0) {
return ret;
}
}
dw_dma_set_channel(addr, ch, (uint32_t)psrcaddr, (uint32_t)pdstaddr, length);
writel(0x1, addr + DMA_REG_Cfg);
dma_priv->status[ch] = DMA_STATE_READY;
return ch;
}
/**
\brief start generate dma signal.
\param[in] handle damc handle to operate.
\param[in] ch channel num.
\return error code
*/
int32_t csi_dma_start(dmac_handle_t handle, int32_t ch)
{
dw_dma_priv_t *dma_priv = handle;
if (handle == NULL || ch >= dma_priv->ch_num || ch < 0) {
return ERR_DMA(DRV_ERROR_PARAMETER);
}
dma_priv->status[ch] = DMA_STATE_BUSY;
uint32_t addr = dma_priv->base;
// interrupt enable
uint32_t value = readl(addr + ch*0x58 + DMA_REG_CTRLax);
value |= CK_DMA_INT_EN;
writel(value, addr + ch*0x58 + DMA_REG_CTRLax);
value = readl(addr + DMA_REG_ChEn);
value |= (CK_DMA_CH_EN << (8+ch)) | (CK_DMA_CH_EN << ch);
writel(value, addr + DMA_REG_ChEn);
return 0;
}
/**
\brief Stop generate dma signal.
\param[in] handle damc handle to operate.
\param[in] ch channel num.
\return error code
*/
int32_t csi_dma_stop(dmac_handle_t handle, int32_t ch)
{
if (handle == NULL) {
return ERR_DMA(DRV_ERROR_PARAMETER);
}
dw_dma_priv_t *dma_priv = handle;
if (ch >= dma_priv->ch_num || ch < 0) {
return ERR_DMA(DRV_ERROR_PARAMETER);
}
dma_priv->status[ch] = DMA_STATE_DONE;
uint32_t addr = dma_priv->base;
// interrupt disable
uint32_t value = readl(addr + ch*0x58 + DMA_REG_CTRLax);
value &= ~CK_DMA_INT_EN;
writel(value, addr + ch*0x58 + DMA_REG_CTRLax);
value = readl(addr + DMA_REG_ChEn);
value |= (CK_DMA_CH_EN << (8+ch));
value &= ~(CK_DMA_CH_EN << ch);
writel(value, addr + DMA_REG_ChEn);
return 0;
}
/**
\brief Get DMA status.
\param[in] handle damc handle to operate.
\param[in] ch channel num.
\return DMA status \ref dma_status_t
*/
dma_status_e csi_dma_get_status(dmac_handle_t handle, int32_t ch)
{
if (handle == NULL) {
return ERR_DMA(DRV_ERROR_PARAMETER);
}
dw_dma_priv_t *dma_priv = handle;
if (ch >= dma_priv->ch_num || ch < 0) {
return ERR_DMA(DRV_ERROR_PARAMETER);
}
return dma_priv->status[ch];
}

View file

@ -0,0 +1,371 @@
/*
* Copyright (C) 2017 C-SKY Microsystems Co., Ltd. All rights reserved.
*
* 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 ck_eflash.c
* @brief CSI Source File for Embedded Flash Driver
* @version V1.0
* @date 02. June 2017
******************************************************************************/
#include <csi_config.h>
#include <stdio.h>
#include <string.h>
#include "drv_eflash.h"
#include "ck_eflash.h"
#define ERR_EFLASH(errno) (CSI_DRV_ERRNO_EFLASH_BASE | errno)
#define EFLASH_NULL_PARAM_CHK(para) \
do { \
if (para == NULL) { \
return ERR_EFLASH(DRV_ERROR_PARAMETER); \
} \
} while (0)
typedef struct {
uint32_t base;
eflash_info_t eflashinfo;
eflash_event_cb_t cb;
eflash_status_t status;
} ck_eflash_priv_t;
extern int32_t target_get_eflash_count(void);
extern int32_t target_get_eflash(int32_t idx, uint32_t *base, eflash_info_t *info);
static ck_eflash_priv_t eflash_handle[CONFIG_EFLASH_NUM];
/* Driver Capabilities */
static const eflash_capabilities_t driver_capabilities = {
.event_ready = 1, /* event_ready */
.data_width = 2, /* data_width = 0:8-bit, 1:16-bit, 2:32-bit */
.erase_chip = 0 /* erase_chip */
};
//
// Functions
//
static int32_t eflash_program_word(eflash_handle_t handle, uint32_t dstaddr, uint32_t *srcbuf, uint32_t len)
{
ck_eflash_priv_t *eflash_priv = handle;
uint32_t fbase = eflash_priv->base;
uint32_t i;
for (i = 0; i < len; i++) {
*(volatile uint32_t *)(fbase + 0x04) = dstaddr;
*(volatile uint32_t *)(fbase + 0x1c) = *srcbuf;
*(volatile uint32_t *)(fbase + 0x18) = 1;
srcbuf++;
dstaddr += 4;
}
return (i << 2);
}
#ifdef CONFIG_CHIP_HOBBIT1_2
static uint32_t context[EFLASH_SECTOR_SIZE >> 2] = {0x0};
static int32_t eflash_verify(eflash_handle_t handle, uint32_t addr, const void *data, uint32_t cnt)
{
uint32_t i;
uint8_t error_flag = 1;
uint8_t *block_addr = (uint8_t *)(addr & ~(EFLASH_SECTOR_SIZE - 1));
uint32_t pre_offset = addr - (uint32_t)block_addr;
uint32_t pre_count = (cnt > (EFLASH_SECTOR_SIZE - pre_offset)) ? (EFLASH_SECTOR_SIZE - pre_offset) : cnt;
uint8_t *p = NULL;
uint8_t *dst = NULL;
p = (uint8_t *)data;
dst = (uint8_t *)addr;
uint32_t len = cnt;
while (error_flag) {
for (i = 0; i < pre_count; i++) {
if (*((uint8_t *)dst + i) != *((uint8_t *)p + i)) {
memcpy(context, block_addr, EFLASH_SECTOR_SIZE);
memcpy((uint8_t *)context + pre_offset, p, EFLASH_SECTOR_SIZE - pre_offset);
csi_eflash_erase_sector(handle, (uint32_t)dst);
eflash_program_word(handle, (uint32_t)block_addr, context, EFLASH_SECTOR_SIZE >> 2);
break;
}
}
if (i == pre_count) {
error_flag = 0;
}
}
error_flag = 1;
p += pre_count;
dst += pre_count;
len -= pre_count;
while (len >= EFLASH_SECTOR_SIZE) {
while (error_flag) {
for(i = 0; i < EFLASH_SECTOR_SIZE; i++) {
if (*((uint8_t *)dst + i) != *((uint8_t *)p + i)) {
memcpy((uint8_t *)context, p, EFLASH_SECTOR_SIZE);
csi_eflash_erase_sector(handle, (uint32_t)dst);
eflash_program_word(handle, (uint32_t)dst, context, EFLASH_SECTOR_SIZE >> 2);
break;
}
}
if (i == EFLASH_SECTOR_SIZE) {
error_flag = 0;
}
}
error_flag = 1;
dst += EFLASH_SECTOR_SIZE;
p += EFLASH_SECTOR_SIZE;
len -= EFLASH_SECTOR_SIZE;
}
if (len > 0) {
while (error_flag) {
for(i = 0; i < len; i++) {
if (*((uint8_t *)dst + i) != *((uint8_t *)p + i)) {
memcpy(context, dst, EFLASH_SECTOR_SIZE);
memcpy((uint8_t *)context + i, p+i, len - i);
csi_eflash_erase_sector(handle, (uint32_t)dst);
eflash_program_word(handle, (uint32_t)dst, context, EFLASH_SECTOR_SIZE >> 2);
break;
}
}
if (i == len) {
error_flag = 0;
}
}
}
return 0;
}
#endif
/**
\brief Initialize EFLASH Interface. 1. Initializes the resources needed for the EFLASH interface 2.registers event callback function
\param[in] idx device id
\param[in] cb_event Pointer to \ref eflash_event_cb_t
\return pointer to eflash handle
*/
eflash_handle_t csi_eflash_initialize(int32_t idx, eflash_event_cb_t cb_event)
{
if (idx < 0 || idx >= CONFIG_EFLASH_NUM) {
return NULL;
}
/* obtain the eflash information */
uint32_t base = 0u;
eflash_info_t info;
int32_t real_idx = target_get_eflash(idx, &base, &info);
if (real_idx != idx) {
return NULL;
}
ck_eflash_priv_t *eflash_priv = &eflash_handle[idx];
eflash_priv->base = base;
eflash_priv->eflashinfo.start = info.start;
eflash_priv->eflashinfo.end = info.end;
eflash_priv->eflashinfo.sector_count = info.sector_count;
/* initialize the eflash context */
eflash_priv->cb = cb_event;
eflash_priv->status.busy = 0;
eflash_priv->status.error = 0U;
eflash_priv->eflashinfo.sector_size = EFLASH_SECTOR_SIZE;
eflash_priv->eflashinfo.page_size = EFLASH_PAGE_SIZE;
eflash_priv->eflashinfo.program_unit = EFLASH_PROGRAM_UINT;
eflash_priv->eflashinfo.erased_value = EFLASH_ERASED_VALUE;
return (eflash_handle_t)eflash_priv;
}
/**
\brief De-initialize EFLASH Interface. stops operation and releases the software resources used by the interface
\param[in] handle eflash handle to operate.
\return error code
*/
int32_t csi_eflash_uninitialize(eflash_handle_t handle)
{
EFLASH_NULL_PARAM_CHK(handle);
ck_eflash_priv_t *eflash_priv = handle;
eflash_priv->cb = NULL;
return 0;
}
/**
\brief Get driver capabilities.
\param[in] idx device id
\return \ref eflash_capabilities_t
*/
eflash_capabilities_t csi_eflash_get_capabilities(int32_t idx)
{
if (idx < 0 || idx >= CONFIG_EFLASH_NUM) {
eflash_capabilities_t ret;
memset(&ret, 0, sizeof(eflash_capabilities_t));
return ret;
}
return driver_capabilities;
}
/**
\brief Read data from Flash.
\param[in] handle eflash handle to operate.
\param[in] addr Data address.
\param[out] data Pointer to a buffer storing the data read from Flash.
\param[in] cnt Number of data items to read.
\return number of data items read or error code
*/
int32_t csi_eflash_read(eflash_handle_t handle, uint32_t addr, void *data, uint32_t cnt)
{
EFLASH_NULL_PARAM_CHK(handle);
EFLASH_NULL_PARAM_CHK(data);
EFLASH_NULL_PARAM_CHK(cnt);
if (!IS_EFLASH_ADDR(addr) || !(IS_EFLASH_ADDR(addr + cnt -1))) {
return ERR_EFLASH(DRV_ERROR_PARAMETER);
}
volatile uint8_t *src_addr = (uint8_t *)addr;
ck_eflash_priv_t *eflash_priv = handle;
if (eflash_priv->status.busy) {
return ERR_EFLASH(DRV_ERROR_BUSY);
}
eflash_priv->status.error = 0U;
int i;
for (i = 0; i < cnt; i++) {
*((uint8_t *)data + i) = *(src_addr + i);
}
return i;
}
/**
\brief Program data to Flash.
\param[in] handle eflash handle to operate.
\param[in] addr Data address.
\param[in] data Pointer to a buffer containing the data to be programmed to Flash..
\param[in] cnt Number of data items to program.
\return number of data items programmed or error code
*/
int32_t csi_eflash_program(eflash_handle_t handle, uint32_t addr, const void *data, uint32_t cnt)
{
EFLASH_NULL_PARAM_CHK(handle);
EFLASH_NULL_PARAM_CHK(data);
EFLASH_NULL_PARAM_CHK(cnt);
if (!IS_EFLASH_ADDR(addr) || !(IS_EFLASH_ADDR(addr + cnt -1))) {
return ERR_EFLASH(DRV_ERROR_PARAMETER);
}
ck_eflash_priv_t *eflash_priv = handle;
if ((addr & 0x3) || ((uint32_t)data & 0x3) || (cnt & 0x3)) {
return ERR_EFLASH(DRV_ERROR_PARAMETER);
}
if (eflash_priv->status.busy) {
return ERR_EFLASH(DRV_ERROR_BUSY);
}
eflash_priv->status.busy = 1U;
eflash_priv->status.error = 0U;
uint32_t ret = eflash_program_word(handle, addr, (uint32_t *)data, cnt >> 2);
eflash_priv->status.busy = 0U;
#ifdef CONFIG_CHIP_HOBBIT1_2
eflash_verify(handle, addr, data, cnt);
#endif
return ret;
}
/**
\brief Erase Flash Sector.
\param[in] handle eflash handle to operate.
\param[in] addr Sector address
\return error code
*/
int32_t csi_eflash_erase_sector(eflash_handle_t handle, uint32_t addr)
{
EFLASH_NULL_PARAM_CHK(handle);
if (!IS_EFLASH_ADDR(addr)) {
return ERR_EFLASH(DRV_ERROR_PARAMETER);
}
addr = addr & ~(EFLASH_SECTOR_SIZE - 1);
ck_eflash_priv_t *eflash_priv = handle;
uint32_t fbase = eflash_priv->base;
if (eflash_priv->status.busy) {
return ERR_EFLASH(DRV_ERROR_BUSY);
}
eflash_priv->status.busy = 1U;
eflash_priv->status.error = 0U;
*(volatile uint32_t *)(fbase + 0x4) = addr;
*(volatile uint32_t *)(fbase + 0x10) = 0x1;
eflash_priv->status.busy = 0U;
return 0;
}
/**
\brief Erase complete Flash.
\param[in] handle eflash handle to operate.
\return error code
*/
int32_t csi_eflash_erase_chip(eflash_handle_t handle)
{
EFLASH_NULL_PARAM_CHK(handle);
return ERR_EFLASH(DRV_ERROR_UNSUPPORTED);
}
/**
\brief Get Flash information.
\param[in] handle eflash handle to operate.
\return Pointer to Flash information \ref eflash_info_t
*/
eflash_info_t *csi_eflash_get_info(eflash_handle_t handle)
{
if (handle == NULL) {
return NULL;
}
ck_eflash_priv_t *eflash_priv = handle;
eflash_info_t *eflash_info = &(eflash_priv->eflashinfo);
return eflash_info;
}
/**
\brief Get EFLASH status.
\param[in] handle eflash handle to operate.
\return EFLASH status \ref eflash_status_t
*/
eflash_status_t csi_eflash_get_status(eflash_handle_t handle)
{
if (handle == NULL) {
eflash_status_t ret;
memset(&ret, 0, sizeof(eflash_status_t));
return ret;
}
ck_eflash_priv_t *eflash_priv = handle;
return eflash_priv->status;
}

View file

@ -0,0 +1,346 @@
/*
* Copyright (C) 2017 C-SKY Microsystems Co., Ltd. All rights reserved.
*
* 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 ck_etb.c
* @brief CSI Source File for ETB Driver
* @version V1.0
* @date 28. Octorber 2017
******************************************************************************/
#include <soc.h>
#include <io.h>
#include <drv_etb.h>
#include <drv_errno.h>
#include <ck_etb.h>
#include <string.h>
#define ERR_ETB(errno) (CSI_DRV_ERRNO_ETB_BASE | errno)
#define ETB_NULL_PARAM_CHK(para) \
do { \
if (para == NULL) { \
return ERR_ETB(DRV_ERROR_PARAMETER); \
} \
} while (0)
typedef struct {
uint32_t base;
uint16_t source;
uint16_t dest;
etb_status_t status;
} ck_etb_priv_t;
extern int32_t target_get_etb_count(void);
extern int32_t target_get_etb(int32_t idx, uint32_t *base, uint32_t *irq);
static ck_etb_priv_t etb_instance[CONFIG_ETB_NUM];
/* Driver Capabilities */
static const etb_capabilities_t etb_capabilities = {
.sync_trigger = 1,
.async_trigger = 1,
.etb_31_channel = 1,
.one_trigger_one = 1,
.one_trigger_more = 1,
.more_trigger_one = 1
};
static uint32_t g_etb_ch3_31_mark[CK_ETB_CH31 - CK_ETB_CH3 + 1] = {0};
static int32_t etb_ch0_config(uint32_t source_loc, uint32_t dest_loc, etb_source_type_e source_type)
{
if (source_loc > CK_ETB_CH0_SOURCE_TRIGGER_MAX || dest_loc > CK_ETB_CH0_DEST_TRIGGER_MAX) {
return -ETB_NO_SUCH_TRIGGER;
}
uint8_t src_trigger = source_loc;
uint8_t dest_trigger = dest_loc;
if (!HAL_IS_BIT_SET(getreg32((volatile uint32_t *)CK_ETB_CFG0_CH0), CK_ETB_SRC0_EN_CH0_BIT)) {
set_bit(CK_ETB_SRC0_EN_CH0_BIT, (volatile uint32_t *)CK_ETB_CFG0_CH0);
write_bits(CK_ETB_CH0_SOURCE_TRIGGER_BITS_WIDTH, CK_ETB_SRC0_EN_CH0_BIT + 1, (volatile uint32_t *)CK_ETB_CFG0_CH0, src_trigger);
} else if (!HAL_IS_BIT_SET(getreg32((volatile uint32_t *)CK_ETB_CFG0_CH0), CK_ETB_SRC1_EN_CH0_BIT)) {
set_bit(CK_ETB_SRC0_EN_CH0_BIT, (volatile uint32_t *)CK_ETB_CFG0_CH0);
write_bits(CK_ETB_CH0_SOURCE_TRIGGER_BITS_WIDTH, CK_ETB_SRC1_EN_CH0_BIT + 1, (volatile uint32_t *)CK_ETB_CFG0_CH0, src_trigger);
} else if (!HAL_IS_BIT_SET(getreg32((volatile uint32_t *)CK_ETB_CFG0_CH0), CK_ETB_SRC2_EN_CH0_BIT)) {
set_bit(CK_ETB_SRC0_EN_CH0_BIT, (volatile uint32_t *)CK_ETB_CFG0_CH0);
write_bits(CK_ETB_CH0_SOURCE_TRIGGER_BITS_WIDTH, CK_ETB_SRC2_EN_CH0_BIT + 1, (volatile uint32_t *)CK_ETB_CFG0_CH0, src_trigger);
} else {
return -ETB_NO_SUCH_CHANNEL_AVAIL;
}
write_bits(CK_ETB_CH0_DEST_TRIGGER_BITS_WIDTH, CK_ETB_CH0_DEST_TRIGGER_BIT_BASE, (volatile uint32_t *)CK_ETB_CFG1_CH0, dest_trigger);
write_bits(1, CK_ETB_TRIGGER_MODE_BIT, (volatile uint32_t *)CK_ETB_CFG1_CH0, source_type);
return CK_ETB_CH0;
}
static int32_t etb_ch1_2_config(uint32_t source_loc, uint32_t dest_loc, etb_source_type_e source_type)
{
if (source_loc > CK_ETB_CH1_SOURCE_TRIGGER_MAX || dest_loc > CK_ETB_CH1_DEST_TRIGGER_MAX) {
return -ETB_NO_SUCH_TRIGGER;
}
uint8_t src_trigger = source_loc;
uint8_t dest_trigger = dest_loc;
int32_t ch_ret;
if (!HAL_IS_BIT_SET(getreg32((volatile uint32_t *)CK_ETB_CFG0_CH1), CK_ETB_DEST0_EN_CH1_BIT)) {
set_bit(CK_ETB_DEST0_EN_CH1_BIT, (volatile uint32_t *)CK_ETB_CFG0_CH1);
write_bits(CK_ETB_CH1_DEST_TRIGGER_BITS_WIDTH, CK_ETB_DEST0_EN_CH1_BIT + 1, (volatile uint32_t *)CK_ETB_CFG0_CH1, dest_trigger);
ch_ret = CK_ETB_CH1;
} else if (!HAL_IS_BIT_SET(getreg32((volatile uint32_t *)CK_ETB_CFG0_CH1), CK_ETB_DEST1_EN_CH1_BIT)) {
set_bit(CK_ETB_DEST0_EN_CH1_BIT, (volatile uint32_t *)CK_ETB_CFG0_CH1);
write_bits(CK_ETB_CH1_DEST_TRIGGER_BITS_WIDTH, CK_ETB_DEST1_EN_CH1_BIT + 1, (volatile uint32_t *)CK_ETB_CFG0_CH1, dest_trigger);
ch_ret = CK_ETB_CH1;
} else if (!HAL_IS_BIT_SET(getreg32((volatile uint32_t *)CK_ETB_CFG0_CH1), CK_ETB_DEST2_EN_CH1_BIT)) {
set_bit(CK_ETB_DEST0_EN_CH1_BIT, (volatile uint32_t *)CK_ETB_CFG0_CH1);
write_bits(CK_ETB_CH1_DEST_TRIGGER_BITS_WIDTH, CK_ETB_DEST2_EN_CH1_BIT + 1, (volatile uint32_t *)CK_ETB_CFG0_CH1, dest_trigger);
ch_ret = CK_ETB_CH1;
} else {
goto next_channel2_label;
}
next_channel2_label:
if (!HAL_IS_BIT_SET(getreg32((volatile uint32_t *)CK_ETB_CFG0_CH2), CK_ETB_DEST0_EN_CH2_BIT)) {
set_bit(CK_ETB_DEST0_EN_CH1_BIT, (volatile uint32_t *)CK_ETB_CFG0_CH1);
write_bits(CK_ETB_CH2_DEST_TRIGGER_BITS_WIDTH, CK_ETB_DEST0_EN_CH2_BIT + 1, (volatile uint32_t *)CK_ETB_CFG0_CH2, dest_trigger);
ch_ret = CK_ETB_CH2;
} else if (!HAL_IS_BIT_SET(getreg32((volatile uint32_t *)CK_ETB_CFG0_CH2), CK_ETB_DEST1_EN_CH2_BIT)) {
set_bit(CK_ETB_DEST0_EN_CH2_BIT, (volatile uint32_t *)CK_ETB_CFG0_CH2);
write_bits(CK_ETB_CH2_DEST_TRIGGER_BITS_WIDTH, CK_ETB_DEST1_EN_CH2_BIT + 1, (volatile uint32_t *)CK_ETB_CFG0_CH2, dest_trigger);
ch_ret = CK_ETB_CH2;
} else if (!HAL_IS_BIT_SET(getreg32((volatile uint32_t *)CK_ETB_CFG0_CH2), CK_ETB_DEST2_EN_CH2_BIT)) {
set_bit(CK_ETB_DEST0_EN_CH2_BIT, (volatile uint32_t *)CK_ETB_CFG0_CH2);
write_bits(CK_ETB_CH2_DEST_TRIGGER_BITS_WIDTH, CK_ETB_DEST2_EN_CH2_BIT + 1, (volatile uint32_t *)CK_ETB_CFG0_CH2, dest_trigger);
ch_ret = CK_ETB_CH2;
} else {
return -ETB_NO_SUCH_CHANNEL_AVAIL;
}
if (ch_ret == CK_ETB_CH1) {
write_bits(CK_ETB_CH1_SOURCE_TRIGGER_BITS_WIDTH, CK_ETB_CH1_SOURCE_TRIGGER_BIT_BASE, (volatile uint32_t *)CK_ETB_CFG1_CH1, src_trigger);
write_bits(1, CK_ETB_TRIGGER_MODE_BIT, (volatile uint32_t *)CK_ETB_CFG1_CH1, source_type);
return CK_ETB_CH1;
} else if (ch_ret == CK_ETB_CH2) {
write_bits(CK_ETB_CH2_SOURCE_TRIGGER_BITS_WIDTH, CK_ETB_CH2_SOURCE_TRIGGER_BIT_BASE, (volatile uint32_t *)CK_ETB_CFG1_CH2, src_trigger);
write_bits(1, CK_ETB_TRIGGER_MODE_BIT, (volatile uint32_t *)CK_ETB_CFG1_CH1, source_type);
return CK_ETB_CH2;
} else {
return -ETB_NO_SUCH_CHANNEL_AVAIL;
}
}
static int32_t search_fresh(void)
{
int i = 0;
for (; i < (CK_ETB_CH31 - CK_ETB_CH3 + 1); i++) {
if (!g_etb_ch3_31_mark[i]) {
return (i + 3);
}
}
return 0;
}
static int32_t etb_ch3_to_31_config(uint32_t source_loc, uint32_t dest_loc, etb_source_type_e source_type)
{
if (source_loc > CK_ETB_CH3_31_SOURCE_TRIGGER_MAX || dest_loc > CK_ETB_CH3_31_DEST_TRIGGER_MAX) {
return -ETB_NO_SUCH_TRIGGER;
}
uint8_t source = source_loc;
uint8_t dest = dest_loc;
uint32_t ch_ret;
ch_ret = search_fresh();
if (ch_ret >= CK_ETB_CH3 && ch_ret <= CK_ETB_CH31) {
write_bits(CK_ETB_CH3_31_SOURCE_TRIGGER_BITS_WIDTH, CK_ETB_CH3_31_SOURCE_BASE_BIT, (volatile uint32_t *)(CK_ETB_CFG_CH3 + 0x4 * (ch_ret -3)), source);
write_bits(CK_ETB_CH3_31_DEST_TRIGGER_BITS_WIDTH, CK_ETB_CH3_31_DEST_BASE_BIT, (volatile uint32_t *)(CK_ETB_CFG_CH3 + 0x4 * (ch_ret -3)), dest);
write_bits(1, CK_ETB_TRIGGER_MODE_BIT, (volatile uint32_t *)(CK_ETB_CFG_CH3 + 0x4 * (ch_ret -3)), source_type);
set_bit(ch_ret, (volatile uint32_t *)(CK_ETB_CFG_CH3 + 0x4 * (ch_ret -3)));
g_etb_ch3_31_mark[ch_ret] = 1;
return ch_ret;
} else {
return -ETB_NO_SUCH_CHANNEL_AVAIL;
}
}
static int32_t channle_op(int32_t channel, int32_t command)
{
if (channel == CK_ETB_CH0) {
write_bits(1, 0, (volatile uint32_t *)CK_ETB_CFG1_CH0, command);
return 0;
} else if (channel == CK_ETB_CH1) {
write_bits(1, 0, (volatile uint32_t *)CK_ETB_CFG1_CH1, command);
return 0;
} else if (channel == CK_ETB_CH2) {
write_bits(1, 0, (volatile uint32_t *)CK_ETB_CFG1_CH2, command);
return 0;
} else if ((channel >= CK_ETB_CH3) && (channel <= CK_ETB_CH31)) {
write_bits(1, 0, (volatile uint32_t *)(CK_ETB_CFG_CH3 + 0x4 * (channel -3)), command);
return 0;
} else {
return -ETB_NO_SUCH_CHANNEL_AVAIL;
}
return -ETB_NO_SUCH_CHANNEL_AVAIL;
}
void ck_etb_irqhandler(int32_t idx)
{
return;
}
/**
\brief get etb instance count.
\return etb instance count
*/
int32_t csi_etb_get_instance_count(void)
{
return target_get_etb_count();
}
/**
\brief Initialize etb Interface. 1. Initializes the resources needed for the etb interface 2.registers event callback function.
\param[in] idx etb index.
\param[in] cb_event event call back function \ref etb_event_cb_t
\return return etb handle if success
*/
etb_handle_t csi_etb_initialize(int32_t idx, etb_event_cb_t cb_event)
{
if (idx != 0) {
return NULL;
}
return (etb_handle_t)etb_instance;
}
/**
\brief De-initialize etb Interface. stops operation and releases the software resources used by the interface
\param[in] handle etb handle to operate.
\return error code
*/
int32_t csi_etb_uninitialize(etb_handle_t handle)
{
ETB_NULL_PARAM_CHK(handle);
return 0;
}
/**
\brief Get driver capabilities.
\param[in] idx etb index.
\return \ref etb_capabilities_t
*/
etb_capabilities_t csi_etb_get_capabilities(int32_t idx)
{
if (idx != 0) {
etb_capabilities_t ret;
memset(&ret, 0, sizeof(etb_capabilities_t));
return ret;
}
return etb_capabilities;
}
/**
\brief config etb channel.
\param[in] handle etb handle to operate.
\param[in] source_lo a specific number represent a location in an source trigger location map to trigger other ip(s).
\param[in] dest_lo a specific number represent an location in an dest trigger map to wait signal(s) from source ip(s) or location(s).
\param[in] source_type \ref etb_source_type_e the input source is hardware trigger or software trigger.
\param[in] mode \ref etb_channel_func_e channel function.
\return channel nubmber or error code (negative).
*/
int32_t csi_etb_channel_config(etb_handle_t handle, uint32_t source_ip, uint32_t dest_ip, etb_source_type_e source_type, etb_channel_func_e mode)
{
ETB_NULL_PARAM_CHK(handle);
int32_t ch_ret;
if (mode == ETB_ONE_TRIGGER_MORE) {
ch_ret = etb_ch1_2_config(source_ip, dest_ip, source_type);
} else if (mode == ETB_MORE_TRIGGER_ONE) {
ch_ret = etb_ch0_config(source_ip, dest_ip, source_type);
} else if (mode == ETB_ONE_TRIGGER_ONE) {
ch_ret = etb_ch3_to_31_config(source_ip, dest_ip, source_type);
} else {
return -ETB_MODE_ERROR;
}
write_bits(1, ch_ret, (volatile uint32_t *)CK_ETB_SOFTTRIG, source_type);
return ch_ret;
}
/**
\brief start etb.
\param[in] handle etb handle to operate.
\param[in] channel etb channel number to operate.
\return error code
*/
int32_t csi_etb_start(etb_handle_t handle, int32_t channel)
{
int32_t ret = 0;
ETB_NULL_PARAM_CHK(handle);
ret = channle_op(channel, CHANNEL_ENABLE_COMMAND);
if (ret < 0) {
return -ETB_NO_SUCH_CHANNEL_AVAIL;
}
set_bit(0, (volatile uint32_t *)CK_ETB_EN);
return 0;
}
/**
\brief stop etb.
\param[in] handle etb handle to operate.
\param[in] channel etb channel number to operate.
\return error code
*/
int32_t csi_etb_stop(etb_handle_t handle, int32_t channel)
{
int32_t ret = 0;
ETB_NULL_PARAM_CHK(handle);
ret = channle_op(channel, CHANNEL_DISABLE_COMMAND);
if (ret < 0) {
return -ETB_NO_SUCH_CHANNEL_AVAIL;
}
clear_bit(0, (volatile uint32_t *)CK_ETB_EN);
return 0;
}
/**
\brief Get ETB status.
\param[in] handle etb handle to operate.
\return ETB status \ref etb_status_t
*/
etb_status_t csi_etb_get_status(etb_handle_t handle)
{
etb_status_t etb_status = {0};
if (handle == NULL) {
return etb_status;
}
ck_etb_priv_t *etb_priv = handle;
return etb_priv->status;
}

View file

@ -0,0 +1,611 @@
/*
* Copyright (C) 2017 C-SKY Microsystems Co., Ltd. All rights reserved.
*
* 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 dw_gpio.c
* @brief CSI Source File for GPIO Driver
* @version V1.0
* @date 02. June 2017
******************************************************************************/
#include <csi_config.h>
#include <stdbool.h>
#include <stdio.h>
#include "drv_gpio.h"
#include "dw_gpio.h"
#include "csi_core.h"
#include "pin_name.h"
#define ERR_GPIO(errno) (CSI_DRV_ERRNO_GPIO_BASE | errno)
#define GPIO_NULL_PARAM_CHK(para) \
do { \
if (para == NULL) { \
return ERR_GPIO(DRV_ERROR_PARAMETER); \
} \
} while (0)
typedef void *gpio_port_handle_t;
typedef struct {
uint32_t base; ///< handle register base
uint32_t irq; ///< irq of this handle
uint32_t pin_num; ///< pin number of this handle
gpio_mode_e mode; ///< gpio mode
gpio_direction_e dir; ///< gpio direction
uint32_t mask; ///< gpio mask bit
uint32_t value; ///< gpio value
} dw_gpio_priv_t;
typedef struct {
uint8_t portidx;
uint8_t idx;
gpio_event_cb_t cb;
} dw_gpio_pin_priv_t;
extern int32_t target_gpio_port_init(port_name_t port, uint32_t *base, uint32_t *irq, uint32_t *pin_num);
extern int32_t target_gpio_pin_init(int32_t gpio_pin, uint32_t *port_idx);
static dw_gpio_priv_t gpio_handle[CONFIG_GPIO_NUM];
static dw_gpio_pin_priv_t gpio_pin_handle[CONFIG_GPIO_PIN_NUM];
//
// Functions
//
static int32_t gpio_set_direction(
void *port,
gpio_direction_e direction
)
{
dw_gpio_priv_t *gpio_priv = port;
dw_gpio_reg_t *gpio_reg = (dw_gpio_reg_t *)(gpio_priv->base);
if (direction == GPIO_DIRECTION_INPUT) {
gpio_reg->SWPORT_DDR &= (~gpio_priv->mask);
} else if (direction == GPIO_DIRECTION_OUTPUT) {
gpio_reg->SWPORT_DDR |= gpio_priv->mask;
} else {
return ERR_GPIO(GPIO_ERROR_DIRECTION);
}
return 0;
}
/*
* Read the statu of the Port choosed.
* Parameters:
* port: use to choose a I/O port among Port A, B, or C.
* return: the value of the corresponding Port.
*/
static int32_t gpio_read(void *port, uint32_t *value)
{
dw_gpio_priv_t *gpio_priv = port;
dw_gpio_control_reg_t *gpio_control_reg = (dw_gpio_control_reg_t *)(gpio_priv->base + 0x30);
*value = gpio_control_reg->EXT_PORTA;
return 0;
}
/*
* Write an output value to corresponding Port.
* Parameters:
* port: use to choose a I/O port among Port A, B, or C.
* output: value that will be written to the corresponding Port.
* return: SUCCESS
*/
static int32_t gpio_write(void *port, uint32_t mask)
{
dw_gpio_priv_t *gpio_priv = port;
dw_gpio_reg_t *gpio_reg = (dw_gpio_reg_t *)(gpio_priv->base);
uint32_t value = gpio_reg->SWPORT_DR;
value &= ~(mask);
value |= gpio_priv->value;
gpio_reg->SWPORT_DR = value;
return 0;
}
/**
* Configure a GPIO gpio_set_irq_mode.
* @param[in] pin the addr store the pin num.
* @param[in] _irqmode the irqmode of gpio
* @return zero on success. -1 on falure.
*/
static int32_t gpio_set_irq_mode(gpio_pin_handle_t pin, gpio_irq_mode_e irq_mode)
{
dw_gpio_pin_priv_t *gpio_pin_priv = pin;
/* convert portidx to port handle */
dw_gpio_priv_t * port_handle = &gpio_handle[gpio_pin_priv->portidx];
dw_gpio_control_reg_t *gpio_control_reg = (dw_gpio_control_reg_t *)(port_handle->base + 0x30);
uint32_t offset = gpio_pin_priv->idx;
uint32_t mask = 1 << offset;
switch (irq_mode) {
/* rising edge interrupt mode */
case GPIO_IRQ_MODE_RISING_EDGE:
gpio_control_reg->INTTYPE_LEVEL |= mask;
gpio_control_reg->INT_POLARITY |= mask;
break;
/* falling edge interrupt mode */
case GPIO_IRQ_MODE_FALLING_EDGE:
gpio_control_reg->INTTYPE_LEVEL |= mask;
gpio_control_reg->INT_POLARITY &= (~mask);
break;
/* low level interrupt mode */
case GPIO_IRQ_MODE_LOW_LEVEL:
gpio_control_reg->INTTYPE_LEVEL &= (~mask);
gpio_control_reg->INT_POLARITY &= (~mask);
break;
/* high level interrupt mode */
case GPIO_IRQ_MODE_HIGH_LEVEL:
gpio_control_reg->INTTYPE_LEVEL &= (~mask);
gpio_control_reg->INT_POLARITY |= mask;
break;
/* double edge interrupt mode */
case GPIO_IRQ_MODE_DOUBLE_EDGE:
return ERR_GPIO(DRV_ERROR_UNSUPPORTED);
default:
return ERR_GPIO(GPIO_ERROR_IRQ_MODE);
}
return 0;
}
/*
* Clear one or more interrupts of PortA.
* Parameters:
* pinno:
* return: SUCCESS.
*/
static void gpio_irq_clear(gpio_pin_handle_t pin, uint32_t idx)
{
dw_gpio_pin_priv_t *gpio_pin_priv = pin;
/* convert portidx to port handle */
dw_gpio_priv_t * port_handle = &gpio_handle[gpio_pin_priv->portidx];
dw_gpio_control_reg_t *gpio_control_reg = (dw_gpio_control_reg_t *)(port_handle->base + 0x30);
gpio_control_reg->PORTA_EOI = idx;
}
/*
* Enable one or more interrupts of PortA.
* Parameters:
* pinno:
* return: SUCCESS.
*/
static void gpio_irq_enable(gpio_pin_handle_t pin)
{
dw_gpio_pin_priv_t *gpio_pin_priv = pin;
/* convert portidx to port handle */
dw_gpio_priv_t * port_handle = &gpio_handle[gpio_pin_priv->portidx];
dw_gpio_control_reg_t *gpio_control_reg = (dw_gpio_control_reg_t *)(port_handle->base + 0x30);
uint32_t offset = gpio_pin_priv->idx;
uint32_t val = gpio_control_reg->INTEN;
val |= (1 << offset);
gpio_control_reg->INTEN = val;
}
/*
* Disable one or more interrupts of PortA.
* Parameters:
* pinno:
* return: SUCCESS.
*/
static void gpio_irq_disable(gpio_pin_handle_t pin)
{
dw_gpio_pin_priv_t *gpio_pin_priv = pin;
uint32_t offset = gpio_pin_priv->idx;
/* convert portidx to port handle */
dw_gpio_priv_t * port_handle = &gpio_handle[gpio_pin_priv->portidx];
dw_gpio_control_reg_t *gpio_control_reg = (dw_gpio_control_reg_t *)(port_handle->base + 0x30);
uint32_t val = gpio_control_reg->INTEN;
val &= ~(1 << offset);
gpio_control_reg->INTEN = val;
}
void dw_gpio_irqhandler(int idx)
{
dw_gpio_control_reg_t *gpio_control_reg = (dw_gpio_control_reg_t *)(gpio_handle[idx].base + 0x30);
uint32_t value = gpio_control_reg->INTSTATUS;
uint8_t i;
/* find the interrput pin */
for (i = 0; i < 32; i++) {
if (value == (1 << i)) {
break;
}
}
uint32_t offset = i;
uint32_t pin_idx = offset;
for (i = 0; i < idx; i++) {
pin_idx += gpio_handle[i].pin_num;
}
dw_gpio_pin_priv_t *gpio_pin_priv = (dw_gpio_pin_priv_t *)&gpio_pin_handle[pin_idx];
/* execute the callback function */
if ((gpio_event_cb_t)(gpio_pin_priv->cb) && offset != 32) {
((gpio_event_cb_t)(gpio_pin_priv->cb))(pin_idx);
}
gpio_irq_clear(gpio_pin_priv, value); //clear the gpio interrupt
}
/**
\brief Initialize GPIO module. 1. Initializes the resources needed for the GPIO handle 2.registers event callback function
3.get gpio_port_handle
\param[in] port port_name.
\return gpio_port_handle
*/
gpio_port_handle_t csi_gpio_port_initialize(int32_t port)
{
uint32_t i;
dw_gpio_priv_t *gpio_priv = NULL;
for (i = 0; i <= port; i++) {
/* obtain the gpio port information */
uint32_t base = 0u;
uint32_t pin_num;
uint32_t irq;
uint32_t idx = target_gpio_port_init(i, &base, &irq, &pin_num);
if (idx < 0 || idx >= CONFIG_GPIO_NUM) {
return NULL;
}
gpio_priv = &gpio_handle[idx];
gpio_priv->base = base;
gpio_priv->irq = irq;
gpio_priv->pin_num = pin_num;
}
csi_vic_enable_irq(gpio_priv->irq);
return (gpio_port_handle_t)gpio_priv;
}
/**
\brief De-initialize GPIO handle. stops operation and releases the software resources used by the handle
\param[in] handle gpio port handle to operate.
\return error code
*/
int32_t csi_gpio_port_uninitialize(gpio_port_handle_t handle)
{
GPIO_NULL_PARAM_CHK(handle);
dw_gpio_priv_t *gpio_priv = handle;
csi_vic_disable_irq(gpio_priv->irq);
return 0;
}
/**
\brief config multiple pin within one handle
\param[in] handle gpio port handle to operate.
\param[in] mask the bitmask to identify which bits in the handle should be included (0 - ignore)
\param[in] mode \ref gpio_mode_e
\param[in] dir \ref gpio_direction_e
\return error code
*/
int32_t csi_gpio_port_config(gpio_port_handle_t handle, uint32_t mask, gpio_mode_e mode, gpio_direction_e dir)
{
if (mask < 0) {
return ERR_GPIO(DRV_ERROR_PARAMETER);
}
GPIO_NULL_PARAM_CHK(handle);
dw_gpio_priv_t *gpio_priv = handle;
/*config the gpio mode direction mask bits */
switch (mode) {
case GPIO_MODE_PULLNONE:
gpio_priv->mode = mode;
break;
case GPIO_MODE_PULLUP:
case GPIO_MODE_PULLDOWM:
case GPIO_MODE_OPEN_DRAIN:
case GPIO_MODE_PUSH_PULL:
return ERR_GPIO(DRV_ERROR_UNSUPPORTED);
default:
return ERR_GPIO(GPIO_ERROR_MODE);
}
gpio_priv->dir = dir;
gpio_priv->mask = mask;
uint32_t ret = gpio_set_direction(gpio_priv, dir);
return ret;
}
/**
\brief Write value to the handle(write value to multiple pins on one handle at the same time)
\param[in] handle gpio port handle to operate.
\param[in] mask The bitmask to identify which bits in the handle should be included (0 - ignore)
\param[in] value the value to be set
\return error code
*/
int32_t csi_gpio_port_write(gpio_port_handle_t handle, uint32_t mask, uint32_t value)
{
if (mask < 0 || value < 0) {
return ERR_GPIO(DRV_ERROR_PARAMETER);
}
GPIO_NULL_PARAM_CHK(handle);
uint32_t port_value = mask & value;
dw_gpio_priv_t *gpio_priv = handle;
gpio_priv->value = port_value;
gpio_write(gpio_priv, mask);
return 0;
}
/**
\brief Read the current value on the handle(read value of multiple pins on one handle at the same time)
\param[in] handle gpio port handle to operate.
\param[in] mask The bitmask to identify which bits in the handle should be included (0 - ignore)
\param[out] value an integer with each bit corresponding to an associated handle pin setting
\return error code
*/
int32_t csi_gpio_port_read(gpio_port_handle_t handle, uint32_t mask, uint32_t *value)
{
if (mask < 0) {
return ERR_GPIO(DRV_ERROR_PARAMETER);
}
GPIO_NULL_PARAM_CHK(handle);
GPIO_NULL_PARAM_CHK(value);
uint32_t port_value = 0;
gpio_read(handle, &port_value);
*value = (mask & port_value);
return 0;
}
/**
\brief Initialize GPIO handle.
\param[in] gpio_pin Pointer to the int32_t.
\param[in] cb_event Pointer to \ref gpio_event_cb_t.
\param[in] arg Pointer to \ref arg used for the callback.
\return gpio_pin_handle
*/
gpio_pin_handle_t csi_gpio_pin_initialize(int32_t gpio_pin, gpio_event_cb_t cb_event)
{
if (gpio_pin < 0 || gpio_pin >= CONFIG_GPIO_PIN_NUM) {
return NULL;
}
uint32_t i;
for (i = 0; i < CONFIG_GPIO_NUM; i++) {
csi_gpio_port_initialize(i);
}
/* obtain the gpio pin information */
uint32_t port_idx;
uint32_t pin_idx = target_gpio_pin_init(gpio_pin, &port_idx);
uint32_t idx = pin_idx;
for (i = 0; i < port_idx; i++) {
idx += (gpio_handle[i].pin_num);
}
dw_gpio_pin_priv_t *gpio_pin_priv = &(gpio_pin_handle[idx]);
gpio_pin_priv->portidx = port_idx;
gpio_pin_priv->idx = pin_idx;
gpio_pin_priv->cb = cb_event;
return (gpio_pin_handle_t)gpio_pin_priv;
}
/**
\brief De-initialize GPIO pin handle. stops operation and releases the software resources used by the handle
\param[in] handle gpio pin handle to operate.
\return error code
*/
int32_t csi_gpio_pin_uninitialize(gpio_pin_handle_t handle)
{
if (handle == NULL) {
return ERR_GPIO(DRV_ERROR_PARAMETER);
}
dw_gpio_pin_priv_t *gpio_pin_priv = (dw_gpio_pin_priv_t *)handle;
gpio_pin_priv->cb = NULL;
dw_gpio_priv_t * gpio_priv = &gpio_handle[gpio_pin_priv->portidx];
csi_vic_disable_irq(gpio_priv->irq);
return 0;
}
/**
\brief config pin mode
\param[in] pin gpio pin handle to operate.
\param[in] mode \ref gpio_mode_e
\return error code
*/
int32_t csi_gpio_pin_config_mode(gpio_pin_handle_t handle,
gpio_mode_e mode)
{
return ERR_GPIO(DRV_ERROR_UNSUPPORTED);
}
/**
\brief config pin direction
\param[in] pin gpio pin handle to operate.
\param[in] dir \ref gpio_direction_e
\return error code
*/
int32_t csi_gpio_pin_config_direction(gpio_pin_handle_t handle,
gpio_direction_e dir)
{
GPIO_NULL_PARAM_CHK(handle);
/* config the gpio pin mode direction mask bits */
dw_gpio_pin_priv_t *gpio_pin_priv = handle;
/* convert portidx to port handle */
dw_gpio_priv_t * gpio_priv = &gpio_handle[gpio_pin_priv->portidx];
gpio_priv->dir = dir;
gpio_priv->mask = 1 << gpio_pin_priv->idx;
uint32_t ret = gpio_set_direction(gpio_priv, dir);
if(ret) {
return ret;
}
return 0;
}
/**
\brief config pin
\param[in] handle gpio pin handle to operate.
\param[in] mode \ref gpio_mode_e
\param[in] dir \ref gpio_direction_e
\return error code
*/
int32_t csi_gpio_pin_config(gpio_pin_handle_t handle,
gpio_mode_e mode,
gpio_direction_e dir)
{
GPIO_NULL_PARAM_CHK(handle);
/* config the gpio pin mode direction mask bits */
dw_gpio_pin_priv_t *gpio_pin_priv = handle;
/* convert portidx to port handle */
dw_gpio_priv_t * gpio_priv = &gpio_handle[gpio_pin_priv->portidx];
gpio_priv->mode = mode;
gpio_priv->dir = dir;
gpio_priv->mask = 1 << gpio_pin_priv->idx;
uint32_t ret = gpio_set_direction(gpio_priv, dir);
if(ret) {
return ret;
}
return 0;
}
/**
\brief Set one or zero to the selected GPIO pin.
\param[in] handle gpio pin handle to operate.
\param[in] value the value to be set
\return error code
*/
int32_t csi_gpio_pin_write(gpio_pin_handle_t handle, bool value)
{
GPIO_NULL_PARAM_CHK(handle);
if ((int32_t)value < 0) {
return ERR_GPIO(DRV_ERROR_PARAMETER);
}
dw_gpio_pin_priv_t *gpio_pin_priv = handle;
/* convert portidx to port handle */
dw_gpio_priv_t * port_handle = &gpio_handle[gpio_pin_priv->portidx];
uint8_t offset = gpio_pin_priv->idx;
uint32_t port_value = value << offset;
port_handle->value = port_value;
gpio_write(port_handle, (1 << offset));
return 0;
}
/**
\brief Get the value of selected GPIO pin.
\param[in] handle gpio pin handle to operate.
\param[out] value buf to store the pin value
\return error code
*/
int32_t csi_gpio_pin_read(gpio_pin_handle_t handle, bool *value)
{
GPIO_NULL_PARAM_CHK(handle);
if (value <= 0) {
return ERR_GPIO(DRV_ERROR_PARAMETER);
}
dw_gpio_pin_priv_t *gpio_pin_priv = handle;
uint32_t port_value;
uint8_t offset = gpio_pin_priv->idx;
/* convert portidx to port handle */
dw_gpio_priv_t * port_handle = &gpio_handle[gpio_pin_priv->portidx];
gpio_read(port_handle, &port_value);
*value = (port_value & (1 << offset)) >> offset;
return 0;
}
/**
\brief set GPIO interrupt mode.
\param[in] handle gpio pin handle to operate.
\param[in] mode the irq mode to be set
\param[in] enable the enable flag
\return error code
*/
int32_t csi_gpio_pin_set_irq(gpio_pin_handle_t handle, gpio_irq_mode_e mode, bool enable)
{
GPIO_NULL_PARAM_CHK(handle);
uint32_t ret = 0;
if (enable) {
ret = gpio_set_irq_mode(handle, mode);
if (ret) {
return ret;
}
gpio_irq_enable(handle);
} else {
gpio_irq_disable(handle);
}
return ret;
}

View file

@ -0,0 +1,741 @@
/*
* Copyright (C) 2017 C-SKY Microsystems Co., Ltd. All rights reserved.
*
* 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 dw_iic.c
* @brief CSI Source File for IIC Driver
* @version V1.0
* @date 02. June 2017
******************************************************************************/
#include <csi_config.h>
#include "drv_iic.h"
#include "dw_iic.h"
#include "soc.h"
#include "csi_core.h"
#include "string.h"
#define ERR_IIC(errno) (CSI_DRV_ERRNO_I2C_BASE | errno)
#define IIC_NULL_PARAM_CHK(para) \
do { \
if (para == NULL) { \
return ERR_IIC(DRV_ERROR_PARAMETER); \
} \
} while (0)
typedef struct {
uint32_t base;
uint32_t irq;
iic_event_cb_t cb_event;
uint32_t rx_total_num;
uint32_t tx_total_num;
uint8_t *rx_buf;
uint8_t *tx_buf;
volatile uint32_t rx_cnt;
volatile uint32_t tx_cnt;
uint32_t status; ///< status of iic transfer
} dw_iic_priv_t;
extern int32_t target_iic_init(int32_t idx, uint32_t *base, uint32_t *irq);
static dw_iic_priv_t iic_instance[CONFIG_IIC_NUM];
static const iic_capabilities_t iic_capabilities = {
.address_10_bit = 0 /* supports 10-bit addressing */
};
static inline void dw_iic_disable(dw_iic_reg_t *addr)
{
/* First clear ACTIVITY, then Disable IIC */
addr->IC_CLR_ACTIVITY;
addr->IC_ENABLE = DW_IIC_DISABLE;
}
static inline void dw_iic_enable(dw_iic_reg_t *addr)
{
addr->IC_ENABLE = DW_IIC_ENABLE;
}
static inline void dw_iic_set_transfer_speed(dw_iic_reg_t *addr, DWENUM_IIC_SPEED speed)
{
uint16_t temp = addr->IC_CON;
temp &= ~((1 << 1) + (1 << 2));
temp |= speed << 1;
addr->IC_CON = temp;
}
static inline void dw_iic_set_target_address(dw_iic_reg_t *addr, uint16_t address)
{
uint16_t temp = addr->IC_TAR;
temp &= 0xfc00;
temp |= address;
addr->IC_TAR = temp;
}
static inline void dw_iic_set_addr_mode(dw_iic_reg_t *addr, iic_address_mode_e addr_mode)
{
uint16_t temp = addr->IC_TAR;
temp &= 0xefff;
temp |= addr_mode << 12;
addr->IC_TAR = temp;
}
static uint32_t dw_iic_read_clear_intrbits(dw_iic_reg_t *addr)
{
uint32_t stat = 0;
stat = addr->IC_INTR_STAT;
if (stat & DW_IIC_INTR_RX_UNDER)
addr->IC_CLR_RX_UNDER;
if (stat & DW_IIC_INTR_RX_OVER)
addr->IC_CLR_RX_OVER;
if (stat & DW_IIC_INTR_TX_OVER)
addr->IC_CLR_TX_OVER;
if (stat & DW_IIC_INTR_RD_REQ)
addr->IC_CLR_RD_REQ;
if (stat & DW_IIC_INTR_TX_ABRT)
addr->IC_TX_ABRT_SOURCE;
if (stat & DW_IIC_INTR_RX_DONE)
addr->IC_CLR_RX_DONE;
if (stat & DW_IIC_INTR_ACTIVITY)
addr->IC_CLR_ACTIVITY;
if (stat & DW_IIC_INTR_STOP_DET)
addr->IC_CLR_STOP_DET;
if (stat & DW_IIC_INTR_START_DET)
addr->IC_CLR_START_DET;
if (stat & DW_IIC_INTR_GEN_CALL)
addr->IC_CLR_GEN_CALL;
return stat;
}
/**
\brief interrupt service function for transmit FIFO empty interrupt.
\param[in] iic_priv pointer to iic private.
*/
static void dw_iic_intr_tx_empty(int32_t idx, dw_iic_priv_t *iic_priv, uint32_t intr_stat)
{
dw_iic_reg_t *addr = (dw_iic_reg_t *)(iic_priv->base);
if (intr_stat & DW_IIC_INTR_TX_EMPTY) {
uint32_t remain_txfifo = iic_priv->tx_total_num - iic_priv->tx_cnt;
uint8_t emptyfifo = (remain_txfifo > (DW_IIC_FIFO_MAX_LV - addr->IC_TXFLR)) ? DW_IIC_FIFO_MAX_LV - addr->IC_TXFLR : remain_txfifo;
uint32_t i = 0u;
for (i = 0; i < emptyfifo; i++) {
addr->IC_DATA_CMD = *iic_priv->tx_buf++;
}
iic_priv->tx_cnt += emptyfifo;
if (iic_priv->tx_cnt == iic_priv->tx_total_num) {
addr->IC_INTR_MASK &= ~DW_IIC_INTR_TX_EMPTY;
}
}
if (intr_stat & DW_IIC_INTR_TX_OVER) {
iic_priv->status = IIC_STATE_ERROR;
dw_iic_disable(addr);
addr->IC_FIFO_RST_EN = DW_IIC_FIFO_RST_EN;
if (iic_priv->cb_event) {
iic_priv->cb_event(idx, I2C_EVENT_BUS_ERROR);
}
}
if (intr_stat & DW_IIC_INTR_STOP_DET) {
iic_priv->status = IIC_STATE_SEND_DONE;
if (iic_priv->tx_cnt != iic_priv->tx_total_num) {
addr->IC_INTR_MASK &= ~DW_IIC_INTR_TX_EMPTY;
}
dw_iic_disable(addr);
addr->IC_FIFO_RST_EN = DW_IIC_FIFO_RST_EN;
if (iic_priv->cb_event) {
iic_priv->cb_event(idx, I2C_EVENT_TRANSFER_DONE);
}
}
}
/**
\brief interrupt service function for receive FIFO full interrupt .
\param[in] iic_priv pointer to iic private.
*/
static void dw_iic_intr_rx_full(int32_t idx, dw_iic_priv_t *iic_priv, uint32_t intr_stat)
{
dw_iic_reg_t *addr = (dw_iic_reg_t *)(iic_priv->base);
if (intr_stat & DW_IIC_INTR_RX_FULL) {
*iic_priv->rx_buf++ = ((addr->IC_DATA_CMD) & 0xff);
iic_priv->rx_cnt++;;
if (iic_priv->rx_cnt != iic_priv->rx_total_num) {
addr->IC_DATA_CMD = 1 << 8;
}
}
if (intr_stat & DW_IIC_INTR_RX_OVER) {
iic_priv->status = IIC_STATE_ERROR;
addr->IC_DATA_CMD = 0;
dw_iic_disable(addr);
if (iic_priv->cb_event) {
iic_priv->cb_event(idx, I2C_EVENT_BUS_ERROR);
}
}
if (intr_stat & DW_IIC_INTR_STOP_DET) {
if (iic_priv->rx_cnt == iic_priv->rx_total_num) {
iic_priv->status = IIC_STATE_RECV_DONE;
addr->IC_INTR_MASK = 0;
dw_iic_disable(addr);
if (iic_priv->cb_event) {
iic_priv->cb_event(idx, I2C_EVENT_TRANSFER_DONE);
}
}
}
}
void dw_iic_irqhandler(int32_t idx)
{
dw_iic_priv_t *iic_priv = &iic_instance[idx];
dw_iic_reg_t *addr = (dw_iic_reg_t *)(iic_priv->base);
uint32_t intr_stat = dw_iic_read_clear_intrbits(addr);
if (intr_stat & DW_IIC_INTR_TX_ABRT) {
/* If arbitration fault, it indicates either a slave device not
* responding as expected, or other master which is not supported
* by this SW.
*/
iic_priv->status = IIC_STATE_DONE;
dw_iic_disable(addr);
addr->IC_INTR_MASK = 0;
addr->IC_FIFO_RST_EN = DW_IIC_FIFO_RST_EN;
if (iic_priv->cb_event) {
iic_priv->cb_event(idx, I2C_EVENT_BUS_ERROR);
return;
}
}
switch (iic_priv->status) {
/* send data to slave */
case IIC_STATE_DATASEND: {
dw_iic_intr_tx_empty(idx, iic_priv, intr_stat);
break;
}
/* wait for data from slave */
case IIC_STATE_WFDATA: {
dw_iic_intr_rx_full(idx, iic_priv, intr_stat);
break;
}
/* unexpected state,SW fault */
default: {
addr->IC_FIFO_RST_EN = DW_IIC_FIFO_RST_EN;
addr->IC_INTR_MASK = 0;
dw_iic_disable(addr);
if (iic_priv->cb_event) {
iic_priv->cb_event(idx, I2C_EVENT_ARBITRATION_LOST);
}
}
}
}
/**
\brief Initialize IIC Interface specified by pins. \n
1. Initializes the resources needed for the IIC interface 2.registers event callback function
\param[in] idx iic index
\param[in] cb_event Pointer to \ref iic_event_cb_t
\return 0 for success, negative for error code
*/
iic_handle_t csi_iic_initialize(int32_t idx, iic_event_cb_t cb_event)
{
uint32_t base = 0u;
uint32_t irq = 0u;
int32_t ret = target_iic_init(idx, &base, &irq);
if (ret < 0 || ret >= CONFIG_IIC_NUM) {
return NULL;
}
dw_iic_priv_t *iic_priv = &iic_instance[idx];
iic_priv->base = base;
iic_priv->irq = irq;
iic_priv->cb_event = cb_event;
iic_priv->rx_total_num = 0;
iic_priv->tx_total_num = 0;
iic_priv->rx_buf = NULL;
iic_priv->tx_buf = NULL;
iic_priv->rx_cnt = 0;
iic_priv->tx_cnt = 0;
iic_priv->status = 0;
dw_iic_reg_t *addr = (dw_iic_reg_t *)(iic_priv->base);
/* mask all interrupts */
addr->IC_INTR_MASK = 0x00;
addr->IC_CON = DW_IIC_CON_DEFAUL;
csi_vic_enable_irq(iic_priv->irq);
return iic_priv;
}
/**
\brief De-initialize IIC Interface. stops operation and releases the software resources used by the interface
\param[in] handle iic handle to operate.
\return error code
*/
int32_t csi_iic_uninitialize(iic_handle_t handle)
{
IIC_NULL_PARAM_CHK(handle);
/* First clear ACTIVITY, then Disable IIC */
dw_iic_priv_t *iic_priv = handle;
dw_iic_reg_t *addr = (dw_iic_reg_t *)(iic_priv->base);
addr->IC_CLR_ACTIVITY;
addr->IC_INTR_MASK = 0x00;
addr->IC_ENABLE = DW_IIC_DISABLE;
iic_priv->cb_event = NULL;
iic_priv->rx_total_num = 0;
iic_priv->tx_total_num = 0;
iic_priv->rx_buf = NULL;
iic_priv->tx_buf = NULL;
iic_priv->rx_cnt = 0;
iic_priv->tx_cnt = 0;
iic_priv->status = 0;
csi_vic_disable_irq(iic_priv->irq);
return 0;
}
/**
\brief Get driver capabilities.
\param[in] idx iic index.
\return \ref iic_capabilities_t
*/
iic_capabilities_t csi_iic_get_capabilities(int32_t idx)
{
if (idx < 0 || idx >= CONFIG_SPI_NUM) {
iic_capabilities_t ret;
memset(&ret, 0, sizeof(iic_capabilities_t));
return ret;
}
return iic_capabilities;
}
/**
\brief config iic.
\param[in] handle iic handle to operate.
\param[in] mode \ref iic_mode_e.if negative, then this attribute not changed
\param[in] speed \ref iic_speed_e.if negative, then this attribute not changed
\param[in] addr_mode \ref iic_address_mode_e.if negative, then this attribute not changed
\param[in] slave_addr slave address.if negative, then this attribute not changed
\return error code
*/
int32_t csi_iic_config(iic_handle_t handle,
iic_mode_e mode,
iic_speed_e speed,
iic_address_mode_e addr_mode,
int32_t slave_addr)
{
int32_t ret;
ret = csi_iic_config_mode(handle,mode);
if(ret < 0) {
return ret;
}
ret = csi_iic_config_speed(handle,speed);
if(ret < 0) {
return ret;
}
ret = csi_iic_config_addr_mode(handle,addr_mode);
if(ret < 0) {
return ret;
}
ret = csi_iic_config_slave_addr(handle,slave_addr);
if(ret < 0) {
return ret;
}
return 0;
}
/**
\brief config iic mode.
\param[in] handle iic handle to operate.
\param[in] mode \ref iic_mode_e.if negative, then this attribute not changed
\return error code
*/
int32_t csi_iic_config_mode(iic_handle_t handle, iic_mode_e mode)
{
IIC_NULL_PARAM_CHK(handle);
if ((int32_t)mode < 0) {
return 0;
}
switch (mode) {
case IIC_MODE_MASTER:
break;
case IIC_MODE_SLAVE:
return ERR_IIC(DRV_ERROR_UNSUPPORTED);
break;
default:
return ERR_IIC(DRV_ERROR_PARAMETER);
}
return 0;
}
/**
\brief config iic speed.
\param[in] handle iic handle to operate.
\param[in] speed \ref iic_speed_e.if negative, then this attribute not changed
\return error code
*/
int32_t csi_iic_config_speed(iic_handle_t handle, iic_speed_e speed)
{
IIC_NULL_PARAM_CHK(handle);
if ((int32_t)speed < 0) {
return 0;
}
dw_iic_reg_t *addr = (dw_iic_reg_t *)(((dw_iic_priv_t *)handle)->base);
switch (speed) {
case I2C_BUS_SPEED_STANDARD:
dw_iic_set_transfer_speed(addr, DW_IIC_STANDARDSPEED);
break;
case I2C_BUS_SPEED_FAST:
dw_iic_set_transfer_speed(addr, DW_IIC_FASTSPEED);
break;
case I2C_BUS_SPEED_FAST_PLUS:
return ERR_IIC(DRV_ERROR_UNSUPPORTED);
case I2C_BUS_SPEED_HIGH:
dw_iic_set_transfer_speed(addr, DW_IIC_HIGHSPEED);
break;
default:
return ERR_IIC(DRV_ERROR_PARAMETER);
}
return 0;
}
/**
\brief config iic address mode.
\param[in] handle iic handle to operate.
\param[in] addr_mode \ref iic_address_mode_e.if negative, then this attribute not changed
\return error code
*/
int32_t csi_iic_config_addr_mode(iic_handle_t handle, iic_address_mode_e addr_mode)
{
IIC_NULL_PARAM_CHK(handle);
if ((int32_t)addr_mode < 0) {
return 0;
}
dw_iic_reg_t *addr = (dw_iic_reg_t *)(((dw_iic_priv_t *)handle)->base);
switch (addr_mode) {
case I2C_ADDRESS_10BIT:
case I2C_ADDRESS_7BIT:
dw_iic_set_addr_mode(addr, addr_mode);
break;
default:
return ERR_IIC(DRV_ERROR_PARAMETER);
}
return 0;
}
/**
\brief config iic slave address.
\param[in] handle iic handle to operate.
\param[in] slave_addr slave address.if negative, then this attribute not changed
\return error code
*/
int32_t csi_iic_config_slave_addr(iic_handle_t handle, int32_t slave_addr)
{
IIC_NULL_PARAM_CHK(handle);
if (slave_addr < 0) {
return 0;
}
dw_iic_reg_t *addr = (dw_iic_reg_t *)(((dw_iic_priv_t *)handle)->base);
dw_iic_set_target_address(addr, slave_addr);
return 0;
}
/**
\brief Start transmitting data as I2C Master.
This function is non-blocking,\ref iic_event_e is signaled when transfer completes or error happens.
\ref csi_iic_get_status can indicates transmission status.
\param[in] handle iic handle to operate.
\param[in] devaddr iic addrress of slave device.
\param[in] data data to send to I2C Slave
\param[in] num Number of data items to send
\param[in] xfer_pending Transfer operation is pending - Stop condition will not be generated
\return 0 for success, negative for error code
*/
int32_t csi_iic_master_send(iic_handle_t handle, uint32_t devaddr,const void *data, uint32_t num, bool xfer_pending)
{
IIC_NULL_PARAM_CHK(handle);
if (data == NULL || num == 0) {
return ERR_IIC(DRV_ERROR_PARAMETER);
}
dw_iic_priv_t *iic_priv = handle;
dw_iic_reg_t *addr = (dw_iic_reg_t *)(iic_priv->base);
iic_priv->tx_buf = (uint8_t *)data;
iic_priv->tx_total_num = num;
iic_priv->tx_cnt = 0;
iic_priv->status = IIC_STATE_DATASEND;
dw_iic_disable(addr);
addr->IC_CLR_INTR;
addr->IC_TX_TL = DW_IIC_TXFIFO_LV;
/* open corresponding interrupts */
addr->IC_INTR_MASK = DW_IIC_INTR_DEFAULT_MASK;
dw_iic_enable(addr);
return 0;
}
/**
\brief Start receiving data as I2C Master.
This function is non-blocking,\ref iic_event_e is signaled when transfer completes or error happens.
\ref csi_iic_get_status can indicates transmission status.
\param[in] handle iic handle to operate.
\param[in] devaddr iic addrress of slave device.
\param[out] data Pointer to buffer for data to receive from IIC receiver
\param[in] num Number of data items to receive
\param[in] xfer_pending Transfer operation is pending - Stop condition will not be generated
\return 0 for success, negative for error code
*/
int32_t csi_iic_master_receive(iic_handle_t handle, uint32_t devaddr, void *data, uint32_t num, bool xfer_pending)
{
IIC_NULL_PARAM_CHK(handle);
if (data == NULL || num == 0) {
return ERR_IIC(DRV_ERROR_PARAMETER);
}
dw_iic_priv_t *iic_priv = handle;
iic_priv->rx_buf = (uint8_t *)data;
iic_priv->rx_total_num = num;
iic_priv->rx_cnt = 0;
iic_priv->status = IIC_STATE_WFDATA;
dw_iic_reg_t *addr = (dw_iic_reg_t *)(iic_priv->base);
dw_iic_disable(addr);
addr->IC_CLR_INTR;
addr->IC_RX_TL = DW_IIC_RXFIFO_LV; /* Sets receive FIFO threshold */
dw_iic_enable(addr);
addr->IC_DATA_CMD = 1 << 8;
return 0;
}
/**
\brief Start transmitting data as I2C Slave.
\param[in] handle iic handle to operate.
\param[in] data Pointer to buffer with data to transmit to I2C Master
\param[in] num Number of data items to send
\return error code
*/
int32_t csi_iic_slave_send(iic_handle_t handle, const void *data, uint32_t num)
{
return ERR_IIC(DRV_ERROR_UNSUPPORTED);
}
/**
\fn int32_t csi_iic_slave_receive (iic_handle_t handle, const void *data, uint32_t num)
\brief Start receiving data as I2C Slave.
\param[in] handle iic handle to operate.
\param[out] data Pointer to buffer for data to receive from I2C Master
\param[in] num Number of data items to receive
\return error code
*/
int32_t csi_iic_slave_receive(iic_handle_t handle, const void *data, uint32_t num)
{
return ERR_IIC(DRV_ERROR_UNSUPPORTED);
}
/**
\brief abort transfer.
\param[in] handle iic handle to operate.
\return error code
*/
int32_t csi_iic_abort_transfer(iic_handle_t handle)
{
IIC_NULL_PARAM_CHK(handle);
dw_iic_priv_t *iic_priv = handle;
dw_iic_reg_t *addr = (dw_iic_reg_t *)(iic_priv->base);
dw_iic_disable(addr);
if (iic_priv->status == IIC_STATE_DATASEND) {
addr->IC_FIFO_RST_EN = DW_IIC_FIFO_RST_EN;
}
iic_priv->rx_cnt = 0;
iic_priv->tx_cnt = 0;
iic_priv->rx_buf = NULL;
iic_priv->tx_buf = NULL;
return 0;
}
/**
\brief Get IIC status.
\param[in] handle iic handle to operate.
\return IIC status \ref iic_status_t
*/
iic_status_t csi_iic_get_status(iic_handle_t handle)
{
iic_status_t iic_status = {0};
if (handle == NULL) {
return iic_status;
}
dw_iic_priv_t *iic_priv = handle;
dw_iic_reg_t *addr = (dw_iic_reg_t *)(iic_priv->base);
if ((iic_priv->status == IIC_STATE_DATASEND) || (iic_priv->status == IIC_STATE_WFDATA)) {
iic_status.busy = 1;
}
if (iic_priv->status == IIC_STATE_WFDATA) {
iic_status.direction = 1;
}
if (addr->IC_RAW_INTR_STAT & 0x800) {
iic_status.general_call = 1;
}
if (iic_priv->status == IIC_STATE_ERROR) {
iic_status.bus_error = 1;
}
return iic_status;
}
/**
\brief Get IIC transferred data count.
\param[in] handle iic handle to operate.
\return number of data bytes transferred
*/
uint32_t csi_iic_get_data_count(iic_handle_t handle)
{
uint32_t cnt = 0;
if (handle == NULL) {
return 0;
}
dw_iic_priv_t *iic_priv = handle;
if ((iic_priv->status == IIC_STATE_WFDATA) || (iic_priv->status == IIC_STATE_RECV_DONE)) {
cnt = iic_priv->rx_cnt;
}else if ((iic_priv->status == IIC_STATE_DATASEND) || (iic_priv->status == IIC_STATE_SEND_DONE)){
cnt = iic_priv->tx_cnt;
}
return cnt;
}
/**
\brief control IIC power.
\param[in] handle iic handle to operate.
\param[in] state power state.\ref csi_power_stat_e.
\return error code
*/
int32_t csi_iic_power_control(iic_handle_t handle, csi_power_stat_e state)
{
/* return ERR_IIC(DRV_ERROR_UNSUPPORTED); */
return 0; //FIXME: for xxxxx validation
}
/**
\brief Send START command.
\param[in] handle iic handle to operate.
\return error code
*/
int32_t csi_iic_send_start(iic_handle_t handle)
{
return ERR_IIC(DRV_ERROR_UNSUPPORTED);
}
/**
\brief Send STOP command.
\param[in] handle iic handle to operate.
\return error code
*/
int32_t csi_iic_send_stop(iic_handle_t handle)
{
return ERR_IIC(DRV_ERROR_UNSUPPORTED);
}
/**
\brief Reset I2C peripheral.
\param[in] handle iic handle to operate.
\return error code
\note The action here. Most of the implementation sends stop.
*/
int32_t csi_iic_reset(iic_handle_t handle)
{
return csi_iic_send_stop(handle);
}

View file

@ -0,0 +1,106 @@
/*
* Copyright (C) 2017 C-SKY Microsystems Co., Ltd. All rights reserved.
*
* 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 ck_adc.h
* @brief header file for adc driver
* @version V1.0
* @date 15. October 2017
******************************************************************************/
#ifndef _CK_ADC_H_
#define _CK_ADC_H_
#include <stdio.h>
#include <soc.h>
#define ADC_BUF_CAPABILITY 16
#define SUCCESS 0
#define ADC_PARAM_INVALID 1
#define ADC_USER_BUFFER_LACK 2
#define ADC_MODE_ERROR 3
#define ADC_CHANNEL_ERROR 4
#define ADC_CONVERSION_INFO_ERROR 5
#define ADC_DATA_LOST 6
#define ADC_DATA_OVERFLOW 7
#define ADC_DATA_COMPARE_RIGHT_INTERRUPT_BIT 2
#define ADC_DATA_OVERWRITE_INTERRUPT_BIT 1
#define ADC_CONVERSION_COMLETED_INTERRUPT_BIT 0
#define CK_ADC_SINGLE_MODE 0
#define CK_ADC_SCAN_MODE 1
#define CK_ADC_CONTINUOUS 2
#define CK_ADC_DATA_WIDTH 12
#define CK_ADC_CONTINOUS_MODE_MAX_CONVERT_TIMES 16
#define CK_ADC_SCAN_MODE_MAX_CONVERT_TIMES 1
typedef enum {
CK_ADC_CH0 = 0, /* PA8_WKUP_ADC0_ACMP0P */
CK_ADC_CH1 = 1, /* PA9_BOOT_ADC1_PWMFAULT */
CK_ADC_CH2 = 2, /* PA10_ADC2_TXD0 */
CK_ADC_CH3 = 3, /* PA11_ACMP0N_ADC3_RXD0 */
CK_ADC_CH4 = 4, /* PA12_PWM8_TCK_ADC4 */
CK_ADC_CH5 = 5, /* PA13_PWM9_TMS_ADC5 */
CK_ADC_CH6 = 6, /* PA14_PWM10_ADC6 */
CK_ADC_CH7 = 7, /* PA15_PWM11_ADC7 */
CK_ADC_CH8 = 8, /* PA16_RXD1_ADC8 */
CK_ADC_CH9 = 9, /* PA17_TXD1_ADC9 */
CK_ADC_CH10 = 10, /* PA22_SPI1MISO_PWM0_ADC10 */
CK_ADC_CH11 = 11, /* PA23_SPI1MOSI_PWM1_ADC11 */
CK_ADC_CH12 = 12, /* PA26_CTS2_I2SWS_ADC12 */
CK_ADC_CH13 = 13, /* PA27_RTS2_I2SSD_ADC13 */
CK_ADC_CH14 = 14, /* PC0_SCL1_CTS1_PWM10_ADC14 */
CK_ADC_CH15 = 15 /* PC1_SDA1_RTS1_PWM11_ADC15 */
} CKENUM_ADC_CHANNEL;
#define CK_ADC_CR CSKY_ADC_CTL_BASE /* Offset: 0x000 (R/W) A/D control */
#define CK_ADC_DR (CSKY_ADC_CTL_BASE + 0x4UL) /* Offset: 0x004 (R/W) A/D data */
#define CK_ADC_SR (CSKY_ADC_CTL_BASE + 0x8UL) /* Offset: 0x008 (R/W) A/D status */
#define CK_ADC_CMPR (CSKY_ADC_CTL_BASE + 0xcUL) /* Offset: 0x00c (R/W) A/D comparator */
#define CK_ADC_IE (CSKY_ADC_CTL_BASE + 0x10UL) /* Offset: 0x010 (R/W) A/D interrupt enable */
#define CK_ADC_IEFG (CSKY_ADC_CTL_BASE + 0x14UL) /* Offset: 0x014 (R/W) A/D interrupt falg */
#define CK_ADC_STC (CSKY_ADC_CTL_BASE + 0x18UL) /* Offset: 0x018 (W) A/D start conversion */
#define CK_ADC_SAMSEL (CSKY_ADC_CTL_BASE + 0x1cUL) /* Offset: 0x01c (R/W) A/D sample mode select */
#define CK_ADC_DMACR (CSKY_ADC_CTL_BASE + 0x20UL) /* Offset: 0x020 (R/W) A/D FIFO DMA enable */
#define CK_ADC_DMADL (CSKY_ADC_CTL_BASE + 0x24UL) /* Offset: 0x024 (R/W) A/D DMA receive data level */
#define CK_ADC_CR_ADEN_BIT 0
#define CK_ADC_CR_CMS_1_BIT 1
#define CK_ADC_CR_CMS_2_BIT 2
#define CK_ADC_CR_AOIC_BASE_BIT 3
#define CK_ADC_CR_SEQC_BASE_BIT 8
#define CK_ADC_DR_DATA_BASE_BIT 0
#define CK_ADC_SR_ADEF_BIT 0
#define CK_ADC_SR_CMPF_BIT 1
#define CK_ADC_SR_BUSY_BIT 2
#define CK_ADC_SR_CCC_BASE_BIT 3
#define CK_ADC_SR_VALID_BIT 7
#define CK_ADC_SR_OVERW 8
#define CK_ADC_CMPR_CMPEN_BIT 0
#define CK_ADC_CMPR_CMPCOND_BIT 1
#define CK_ADC_CMPR_CMPCH_BASE_BIT 2
#define CK_ADC_CMPR_CMPMATCNT_BASE_BIT 6
#define CK_ADC_CMPR_CMPD_BASE_BIT 10
#define CK_ADC_STC_ADSTC_BIT 0
#define CK_ADC_SAMSEL_BIT 0
#define CK_ADC_DMACR_BIT 0
#define CK_ADC_DMADL_BASE_BIT 0
#define CK_ADC_VREFP 3.3 /* Unit: volt*/
#endif/* _CK_ADC_H_ */

View file

@ -0,0 +1,54 @@
/*
* Copyright (C) 2017 C-SKY Microsystems Co., Ltd. All rights reserved.
*
* 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 ck_aes.h
* @brief header file for aes driver
* @version V1.0
* @date 02. June 2017
******************************************************************************/
#ifndef _CK_AES_H_
#define _CK_AES_H_
#include <stdio.h>
#include "drv_aes.h"
#include "soc.h"
#define AES_LITTLE_ENDIAN 0x00000100
#define AES_MAX_KEY_LENGTH 32
#define AES_IT_DATAINT 0x4
#define AES_IT_KEYINT 0x2
#define AES_IT_BUSY 0x1
#define AES_IT_ALL 0x7
#define AES_CRYPTO_KEYEXP 0x2
#define AES_WORK_ENABLE_OFFSET 0
#define AES_INT_ENABLE_OFFSET 2
#define AES_MODE_OFFSET 3
#define AES_KEY_LEN_OFFSET 4
#define AES_OPCODE_OFFSET 6
typedef struct {
__IOM uint32_t datain[4]; /* Offset: 0x000 (R/W) Data input 0~127 */
__IOM uint32_t key[8]; /* Offset: 0x010 (R/W) Key 0~255 */
__IOM uint32_t iv[4]; /* Offset: 0x030 (R/W) Initial Vector: 0~127 */
__IOM uint32_t ctrl; /* Offset: 0x040 (R/W) AES Control Register */
__IOM uint32_t state; /* Offset: 0x044 (R/W) AES State Register */
__IOM uint32_t dataout[4]; /* Offset: 0x048 (R/W) Data Output 0~31 */
} ck_aes_reg_t;
#endif

View file

@ -0,0 +1,34 @@
/*
* Copyright (C) 2017 C-SKY Microsystems Co., Ltd. All rights reserved.
*
* 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 ck_crc.h
* @brief header file for crc driver
* @version V1.0
* @date 02. June 2017
******************************************************************************/
#ifndef _CK_CRC_H_
#define _CK_CRC_H_
#include "stdint.h"
#include "soc.h"
typedef struct {
__IOM uint32_t CRC_DATA; /* Offset: 0x000 (W/R) data register */
__IOM uint32_t CRC_SEL; /* Offset: 0x004 (W/R) mode select register for CRC */
__OM uint32_t CRC_INIT; /* Offset: 0x008 (W) initial value register */
} ck_crc_reg_t;
#endif

View file

@ -0,0 +1,75 @@
/*
* Copyright (C) 2017 C-SKY Microsystems Co., Ltd. All rights reserved.
*
* 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 ck_dmac.h
* @brief header file for DMAC Driver
* @version V1.0
* @date 02. June 2017
******************************************************************************/
#ifndef __CK_DMA_H
#define __CK_DMA_H
#include <stdio.h>
#include "soc.h"
#define CK_DMA_MAXCHANNEL 2
#define CK_DMA_INT_EN 1
#define CK_DMA_CH_EN 1
#define CK_DMA_TFR 0x0002
#define CK_DMA_ERR 0x0001
#define CK_DMA_INTC 0x03
#define CK_DMA_MASK 0x03
typedef enum {
DMA_ADDR_INCREMENT = 0,
DMA_ADDR_DECREMENT = 1,
DMA_ADDR_NOCHANGE = 2
} enum_addr_state_e;
typedef enum {
DMA_DATAWIDTH_SIZE8 = 1,
DMA_DATAWIDTH_SIZE16 = 2,
DMA_DATAWIDTH_SIZE32 = 4
} dma_datawidth_e;
typedef enum {
DMA_HANDSHAKING_HARDWARE = 0,
DMA_HANDSHAKING_SOFTWARE = 1,
} dma_handshaking_select_e;
typedef enum {
DMA_PRIORITY0 = 0,
DMA_PRIORITY1 = 1,
DMA_PRIOTITY2 = 2,
DMA_PRIOTITY3 = 3
} dma_priority_t;
typedef struct {
__IOM uint32_t SAR; /* offset: 0x00 (R/W) Channel Source Address Register */
__IOM uint32_t DAR; /* offset: 0x04 (R/W) Channel Destination Address Register */
__IOM uint32_t CHCTRLA; /* offset: 0x08 (R/W) Channel Control Register A */
__IOM uint32_t CHCTRLB; /* offset: 0x0C (R/W) Channel Control Register B */
__IOM uint8_t CHINTM:2; /* offset: 0x10 (R/W) Channel Interrupt Mask Register */
uint8_t RESERVED0[3];
__IM uint8_t CHINTS:2; /* offset: 0x14 (R/ ) Channel Interrupt Status Register */
uint8_t RESERVED1[3];
__IOM uint8_t CHINTC:2; /* offset: 0x18 (R/W) Channel Interrupt Clear Register */
uint8_t RESERVED2[3];
__IOM uint8_t CHSREQ:1; /* offset: 0x1C (R/W) Channel Software Request Register */
uint8_t RESERVED3[3];
__IOM uint8_t CHEN:1; /* offset: 0x20 (R/W) Channel Enable Register */
uint8_t RESERVED4[3];
} ck_dma_reg_t;
#endif /* __CK_DMA_H */

View file

@ -0,0 +1,115 @@
/*
* Copyright (C) 2017 C-SKY Microsystems Co., Ltd. All rights reserved.
*
* 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 ck_dmac_v2.h
* @brief header file for DMAC Driver
* @version V1.0
* @date 02. June 2017
******************************************************************************/
#ifndef __CK_DMAC_V2_H
#define __CK_DMAC_V2_H
#include <stdio.h>
#include <soc.h>
#define CK_DMA_MAXCHANNEL 16
#define CK_DMA_INT_EN 1
#define CK_DMA_CH_EN 1
#define CK_DMA_CH_REQ 1
#define CK_DMACCFG_EN 1
#define CK_DMA_TRGETCMPFR 0x8
#define CK_DMA_HTFR 0x4
#define CK_DMA_TFR 0x2
#define CK_DMA_ERR 0x1
#define CK_DMA_INTC 0x1f
#define CK_DMA_MASK 0x00
#define CK_CHINTM_RESETVALUE 0x0
#define CK_CHINTC_RESETVALUE 0x0
#define CK_DMA_ALL_CAHNNELS_PEND_INTR_VALID 0x0000ffff
#define CK_DMA_ALL_CAHNNELS_DATA_TRANS_BUSY_VALID 0x0000ffff
typedef enum {
DMA_ADDR_INCREMENT = 0,
DMA_ADDR_DECREMENT = 1,
DMA_ADDR_NOCHANGE = 2
} enum_addr_state_e;
typedef enum {
DMA_DATAWIDTH_SIZE8 = 1,
DMA_DATAWIDTH_SIZE16 = 2,
DMA_DATAWIDTH_SIZE32 = 3
} dma_datawidth_e;
typedef enum {
DMA_GROUP_LEN1 = 1,
DMA_GROUP_LEN2 = 2,
DMA_GROUP_LEN3 = 3,
DMA_GROUP_LEN4 = 4,
DMA_GROUP_LEN5 = 5,
DMA_GROUP_LEN6 = 6,
DMA_GROUP_LEN7 = 7,
DMA_GROUP_LEN8 = 8
} dma_group_len_e;
typedef enum {
DMA_HANDSHAKING_HARDWARE = 0,
DMA_HANDSHAKING_SOFTWARE = 1,
} dma_handshaking_select_e;
typedef enum {
DMA_PRIORITY0 = 0,
DMA_PRIORITY1 = 1,
DMA_PRIOTITY2 = 2,
DMA_PRIOTITY3 = 3,
DMA_PRIOTITY4 = 4,
DMA_PRIOTITY5 = 5,
DMA_PRIOTITY6 = 6,
DMA_PRIOTITY7 = 7,
DMA_PRIOTITY8 = 8,
DMA_PRIOTITY9 = 9,
DMA_PRIOTITY10 = 10,
DMA_PRIOTITY11 = 11,
DMA_PRIOTITY12 = 12,
DMA_PRIOTITY13 = 13,
DMA_PRIOTITY14 = 14,
DMA_PRIOTITY15 = 15
} dma_priority_t;
#define CK_V2_DMAC_STATUSCHPEND (CSKY_DMAC0_BASE + 0x330)
#define CK_V2_DMAC_CHSR (CSKY_DMAC0_BASE + 0x330 + 0x8)
#define CK_V2_DMAC_DMACCFG (CSKY_DMAC0_BASE + 0x330 + 0xc)
typedef struct {
__IOM uint32_t SAR; /* offset: 0x00 (R/W) Channel Source Address Register */
__IOM uint32_t DAR; /* offset: 0x04 (R/W) Channel Destination Address Register */
__IOM uint32_t CHCTRLA; /* offset: 0x08 (R/W) Channel Control Register A */
__IOM uint32_t CHCTRLB; /* offset: 0x0C (R/W) Channel Control Register B */
__IOM uint8_t CHINTM:5; /* offset: 0x10 (R/W) Channel Interrupt Mask Register */
uint8_t RESERVED0[3];
__IM uint8_t CHINTS:4; /* offset: 0x14 (R/ ) Channel Interrupt Status Register */
uint8_t RESERVED1[3];
__IOM uint8_t CHINTC:5; /* offset: 0x18 (R/W) Channel Interrupt Clear Register */
uint8_t RESERVED2[3];
__IOM uint8_t CHSREQ:1; /* offset: 0x1C (R/W) Channel Software Request Register */
uint8_t RESERVED3[3];
__IOM uint8_t CHEN:1; /* offset: 0x20 (R/W) Channel Enable Register */
uint8_t RESERVED4[3];
} ck_dma_reg_t;
#endif /* __CK_DMAC_V2_H */

View file

@ -0,0 +1,38 @@
/*
* Copyright (C) 2017 C-SKY Microsystems Co., Ltd. All rights reserved.
*
* 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 ck_eflash.h
* @brief head file for ck eflash
* @version V1.0
* @date 02. June 2017
******************************************************************************/
#ifndef _CK_EFLASH_H_
#define _CK_EFLASH_H_
#include "drv_eflash.h"
#include "soc.h"
#define EFLASH_ADDR_START 0x10000000
#define EFLASH_ADDR_END 0x1003f7ff
#define EFLASH_SECTOR_SIZE 0x200
#define EFLASH_ERASED_VALUE 0xff
#define EFLASH_PROGRAM_UINT 0x4
#define EFLASH_PAGE_SIZE 0
#define BLOCK_SIZE 0x200
#define IS_EFLASH_ADDR(addr) \
((addr >= EFLASH_ADDR_START) && (addr <= EFLASH_ADDR_END))
#endif

View file

@ -0,0 +1,159 @@
/*
* Copyright (C) 2017 C-SKY Microsystems Co., Ltd. All rights reserved.
*
* 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 ck_etb.h
* @brief header file for event trigger block driver
* @version V1.0
* @date 28. octorber 2017
******************************************************************************/
#ifndef _CK_ETB_H_
#define _CK_ETB_H_
#include <soc.h>
#define ETB_CHANNEL_FUNC_ERROR 1
#define ETB_NO_SUCH_TRIGGER 2
#define ETB_NO_SUCH_CHANNEL_AVAIL 3
#define ETB_MODE_ERROR 4
typedef enum {
CK_ETB_CH0 = 0,
CK_ETB_CH1 = 1,
CK_ETB_CH2 = 2,
CK_ETB_CH3 = 3,
CK_ETB_CH4 = 4,
CK_ETB_CH5 = 5,
CK_ETB_CH6 = 6,
CK_ETB_CH7 = 7,
CK_ETB_CH8 = 8,
CK_ETB_CH9 = 9,
CK_ETB_CH10 = 10,
CK_ETB_CH11 = 11,
CK_ETB_CH12 = 12,
CK_ETB_CH13 = 13,
CK_ETB_CH14 = 14,
CK_ETB_CH15 = 15,
CK_ETB_CH16 = 16,
CK_ETB_CH17 = 17,
CK_ETB_CH18 = 18,
CK_ETB_CH19 = 19,
CK_ETB_CH20 = 20,
CK_ETB_CH21 = 22,
CK_ETB_CH23 = 23,
CK_ETB_CH24 = 24,
CK_ETB_CH25 = 25,
CK_ETB_CH26 = 26,
CK_ETB_CH27 = 27,
CK_ETB_CH28 = 28,
CK_ETB_CH29 = 29,
CK_ETB_CH30 = 30,
CK_ETB_CH31 = 31
} CKENUM_ETB_CHANNEL;
#define CK_ETB_EN CSKY_ETB_BASE
#define CK_ETB_SOFTTRIG (CSKY_ETB_BASE + 0x4)
#define CK_ETB_CFG0_CH0 (CSKY_ETB_BASE + 0x8)
#define CK_ETB_CFG1_CH0 (CSKY_ETB_BASE + 0xc)
#define CK_ETB_CFG0_CH1 (CSKY_ETB_BASE + 0x10)
#define CK_ETB_CFG1_CH1 (CSKY_ETB_BASE + 0x14)
#define CK_ETB_CFG0_CH2 (CSKY_ETB_BASE + 0x18)
#define CK_ETB_CFG1_CH2 (CSKY_ETB_BASE + 0x1c)
#define CK_ETB_CFG_CH3 (CSKY_ETB_BASE + 0x30)
#define CK_ETB_CFG_CH4 (CSKY_ETB_BASE + 0x34)
#define CK_ETB_CFG_CH5 (CSKY_ETB_BASE + 0x38)
#define CK_ETB_CFG_CH6 (CSKY_ETB_BASE + 0x3c)
#define CK_ETB_CFG_CH7 (CSKY_ETB_BASE + 0x40)
#define CK_ETB_CFG_CH8 (CSKY_ETB_BASE + 0x44)
#define CK_ETB_CFG_CH9 (CSKY_ETB_BASE + 0x48)
#define CK_ETB_CFG_CH10 (CSKY_ETB_BASE + 0x4c)
#define CK_ETB_CFG_CH11 (CSKY_ETB_BASE + 0x50)
#define CK_ETB_CFG_CH12 (CSKY_ETB_BASE + 0x54)
#define CK_ETB_CFG_CH13 (CSKY_ETB_BASE + 0x58)
#define CK_ETB_CFG_CH14 (CSKY_ETB_BASE + 0x5c)
#define CK_ETB_CFG_CH15 (CSKY_ETB_BASE + 0x60)
#define CK_ETB_CFG_CH16 (CSKY_ETB_BASE + 0x64)
#define CK_ETB_CFG_CH17 (CSKY_ETB_BASE + 0x68)
#define CK_ETB_CFG_CH18 (CSKY_ETB_BASE + 0x6c)
#define CK_ETB_CFG_CH19 (CSKY_ETB_BASE + 0x70)
#define CK_ETB_CFG_CH20 (CSKY_ETB_BASE + 0x74)
#define CK_ETB_CFG_CH21 (CSKY_ETB_BASE + 0x78)
#define CK_ETB_CFG_CH22 (CSKY_ETB_BASE + 0x7c)
#define CK_ETB_CFG_CH23 (CSKY_ETB_BASE + 0x80)
#define CK_ETB_CFG_CH24 (CSKY_ETB_BASE + 0x84)
#define CK_ETB_CFG_CH25 (CSKY_ETB_BASE + 0x88)
#define CK_ETB_CFG_CH26 (CSKY_ETB_BASE + 0x8c)
#define CK_ETB_CFG_CH27 (CSKY_ETB_BASE + 0x90)
#define CK_ETB_CFG_CH28 (CSKY_ETB_BASE + 0x94)
#define CK_ETB_CFG_CH29 (CSKY_ETB_BASE + 0x98)
#define CK_ETB_CFG_CH30 (CSKY_ETB_BASE + 0x9c)
#define CK_ETB_CFG_CH31 (CSKY_ETB_BASE + 0xa0)
#define CK_ETB_TRIGGER_MODE_BIT 1
#define CK_ETB_SRC0_EN_CH0_BIT 0
#define CK_ETB_SRC1_EN_CH0_BIT 10
#define CK_ETB_SRC2_EN_CH0_BIT 20
#define CK_ETB_CH0_SOURCE_TRIGGER_MAX 123
#define CK_ETB_CH0_SOURCE_TRIGGER_BITS_WIDTH 7
#define CK_ETB_CH0_DEST_TRIGGER_MAX 255
#define CK_ETB_CH0_DEST_TRIGGER_BIT_BASE 24
#define CK_ETB_CH0_DEST_TRIGGER_BITS_WIDTH 8
#define CK_ETB_DEST0_EN_CH1_BIT 0
#define CK_ETB_DEST1_EN_CH1_BIT 10
#define CK_ETB_DEST2_EN_CH1_BIT 20
#define CK_ETB_CH1_DEST_TRIGGER_MAX 255
#define CK_ETB_CH1_DEST_TRIGGER_BITS_WIDTH 8
#define CK_ETB_CH1_SOURCE_TRIGGER_MAX 123
#define CK_ETB_CH1_SOURCE_TRIGGER_BIT_BASE 25
#define CK_ETB_CH1_SOURCE_TRIGGER_BITS_WIDTH 7
#define CK_ETB_DEST0_EN_CH2_BIT 0
#define CK_ETB_DEST1_EN_CH2_BIT 10
#define CK_ETB_DEST2_EN_CH2_BIT 20
#define CK_ETB_CH2_DEST_TRIGGER_MAX 255
#define CK_ETB_CH2_DEST_TRIGGER_BITS_WIDTH 8
#define CK_ETB_CH2_SOURCE_TRIGGER_MAX 123
#define CK_ETB_CH2_SOURCE_TRIGGER_BIT_BASE 25
#define CK_ETB_CH2_SOURCE_TRIGGER_BITS_WIDTH 7
#define CK_ETB_CH3_31_SOURCE_TRIGGER_MAX 123
#define CK_ETB_CH3_31_SOURCE_TRIGGER_BITS_WIDTH 7
#define CK_ETB_CH3_31_DEST_TRIGGER_MAX 255
#define CK_ETB_CH3_31_DEST_TRIGGER_BIT_BASE 24
#define CK_ETB_CH3_31_DEST_TRIGGER_BITS_WIDTH 8
#define CK_ETB_CH3_31_SOURCE_BASE_BIT 12
#define CK_ETB_CH3_31_DEST_BASE_BIT 24
#define CHANNEL_ENABLE_COMMAND 1
#define CHANNEL_DISABLE_COMMAND 0
//source location and its' number
typedef enum {
RTC = 0
} CKENUM_ETB_SOURCE_LOCALTION;
//dest location and its' number
typedef enum {
DMA_CH0 = 0
} CKENUM_ETB_DEST_LOCALTION;
#endif /* __CK_ETB_H */

View file

@ -0,0 +1,101 @@
/*
* Copyright (C) 2017 C-SKY Microsystems Co., Ltd. All rights reserved.
*
* 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 ck_pwm.h
* @brief header file for pwm driver
* @version V1.0
* @date 02. June 2017
******************************************************************************/
#ifndef __CK_PWM_H
#define __CK_PWM_H
#include <stdio.h>
#include "soc.h"
typedef enum {
CKENUM_PWM_CH0 = 0,
CKENUM_PWM_CH1 = 1,
CKENUM_PWM_CH2 = 2,
CKENUM_PWM_CH3 = 3,
CKENUM_PWM_CH4 = 4,
CKENUM_PWM_CH5 = 5,
CKENUM_PWM_CH6 = 6,
CKENUM_PWM_CH7 = 7,
CKENUM_PWM_CH8 = 8,
CKENUM_PWM_CH9 = 9,
CKENUM_PWM_CH10 = 10,
CKENUM_PWM_CH11 = 11
} CKENUM_PWM_CHANNEL;
typedef enum {
CKENUM_PWM_COUNT_UP = 0,
CKENUM_PWM_COUNT_UP_DOWN = 1
} CKENUM_PWM_COUNTER_MODE;
typedef struct {
__IOM uint32_t PWMCFG; /* Offset: 0x000 (R/W) PWM configure register */
__IOM uint32_t PWMINVERTTRIG; /* Offset: 0x004 (R/W) PWM signal is inverted register */
__IOM uint32_t PWM01TRIG; /* Offset: 0x008 (R/W) contain the trigger generate compare value */
__IOM uint32_t PWM23TRIG; /* Offset: 0x00C (R/W) contain the trigger generate compare value */
__IOM uint32_t PWM45TRIG; /* Offset: 0x010 (N/A) contain the trigger generate compare value */
__IOM uint32_t PWMINTEN1; /* Offset: 0x014 (R/W) interrupt enable */
__IM uint32_t PWMINTEN2; /* Offset: 0x018 (N/A) interrupt enable */
__IOM uint32_t PWMRIS1; /* Offset: 0x01C (R/ ) raw interrupt status */
__IOM uint32_t PWMRIS2; /* Offset: 0x020 (N/A) raw interrupt status */
__IOM uint32_t PWMIC1; /* Offset: 0x024 (R/W) interrupt clear */
__IOM uint32_t PWMIC2; /* Offset: 0x028 (R/W) interrupt clear */
__IOM uint32_t PWMIS1; /* Offset: 0x02C (R/W) interrupt status */
__IOM uint32_t PWMIS2; /* Offset: 0x030 (R/W) interrupt status */
__IOM uint32_t PWMCTL; /* Offset: 0x034 (R/W) configure the pwm generation blocks */
__IOM uint32_t PWM01LOAD; /* Offset: 0x038 (R/W) contain the load value of the PWM count */
__IOM uint32_t PWM23LOAD; /* Offset: 0x03C (R/W) contain the load value of the PWM count */
__IOM uint32_t PWM45LOAD; /* Offset: 0x040 (N/A) contain the load value of the PWM count */
__IM uint32_t PWM01COUNT; /* Offset: 0x044 (R/ ) contain the current value of the PWM count */
__IM uint32_t PWM23COUNT; /* Offset: 0x048 (R/ ) contain the current value of the PWM count */
__IOM uint32_t PWM45COUNT; /* Offset: 0x04C (N/A) contain the current value of the PWM count */
__IOM uint32_t PWM0CMP; /* Offset: 0x050 (R/W) contain a value to be compared against the counter */
__IOM uint32_t PWM1CMP; /* Offset: 0x054 (R/W) contain a value to be compared against the counter */
__IOM uint32_t PWM2CMP; /* Offset: 0x058 (R/W) contain a value to be compared against the counter */
__IOM uint32_t PWM3CMP; /* Offset: 0x05C (N/A) contain a value to be compared against the counter */
__IOM uint32_t PWM4CMP; /* Offset: 0x060 (N/A) contain a value to be compared against the counter */
__IOM uint32_t PWM5CMP; /* Offset: 0x064 (N/A) contain a value to be compared against the counter */
__IOM uint32_t PWM01DB; /* Offset: 0x068 (R/W) contain the number of clock ticks to delay */
__IOM uint32_t PWM23DB; /* Offset: 0x06C (R/W) contain the number of clock ticks to delayr */
__IOM uint32_t PWM45DB; /* Offset: 0x070 (N/A) contain the number of clock ticks to delay */
__IOM uint32_t CAPCTL; /* Offset: 0x074 (R/W) input capture control */
__IOM uint32_t CAPINTEN; /* Offset: 0x078 (R/W) input capture interrupt enable */
__IM uint32_t CAPRIS; /* Offset: 0x07C (R/ ) input capture raw interrupt status */
__IOM uint32_t CAPIC; /* Offset: 0x080 (R/W) input capture interrupt clear */
__IM uint32_t CAPIS; /* Offset: 0x084 (R/ ) input capture interrupt status */
__IM uint32_t CAP01T; /* Offset: 0x088 (R/ ) input capture count value */
__IM uint32_t CAP23T; /* Offset: 0x08C (R/ ) input capture count value */
__IOM uint32_t CAP45T; /* Offset: 0x090 (N/A) input capture count value */
__IOM uint32_t CAP01MATCH; /* Offset: 0x094 (R/W) input capture match value */
__IOM uint32_t CAP23MATCH; /* Offset: 0x098 (R/W) input capture match value */
__IOM uint32_t CAP45MATCH; /* Offset: 0x09C (N/A) input capture match value */
__IOM uint32_t TIMINTEN; /* Offset: 0x0A0 (R/W) time interrupt enable */
__IM uint32_t TIMRIS; /* Offset: 0x0A4 (R/ ) time raw interrupt stats */
__IOM uint32_t TIMIC; /* Offset: 0x0A8 (R/W) time interrupt clear */
__IM uint32_t TIMIS; /* Offset: 0x0AC (R/ ) time interrupt status */
__IOM uint32_t TIM01LOAD; /* Offset: 0x0B0 (R/W) time load value */
__IOM uint32_t TIM23LOAD; /* Offset: 0x0B4 (R/W) time load value */
__IOM uint32_t TIM45LOAD; /* Offset: 0x0B8 (N/A) time load value */
__IOM uint32_t TIM01COUNT; /* Offset: 0x0BC (R/W) time current count time */
__IOM uint32_t TIM23COUNT; /* Offset: 0x0C0 (R/W) time current count time */
__IOM uint32_t TIM45COUNT; /* Offset: 0x0C4 (R/W) time current count time */
} ck_pwm_reg_t;
#endif /* __CK_PWM_H */

View file

@ -0,0 +1,91 @@
/*
* Copyright (C) 2017 C-SKY Microsystems Co., Ltd. All rights reserved.
*
* 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 ck_rsa.h
* @brief header file for rsa driver
* @version V1.0
* @date 02. June 2017
******************************************************************************/
#ifndef _CK_RSA_H_
#define _CK_RSA_H_
#include <stdio.h>
#include "drv_rsa.h"
#include "soc.h"
#define RSA_KEY_LEN 2048
#define RSA_KEY_BYTE (RSA_KEY_LEN >> 3)
#define RSA_KEY_WORD (RSA_KEY_LEN >> 5)
#define BN_MAX_BITS ((RSA_KEY_LEN << 1) + 32)
#define BN_MAX_BYTES ((BN_MAX_BITS + 7) >> 3)
#define BN_MAX_WORDS ((BN_MAX_BYTES + 3) >> 2)
#define MAX_RSA_LP_CNT 10000
#define GET_KEY_BYTE(k) (k >> 3)
#define GET_KEY_WORD(k) (k >> 5)
#define UINT32_TO_UINT64(data) ((uint64_t)(((uint64_t)(data)) & 0x00000000ffffffffU))
#define UINT64L_TO_UINT32(data) ((uint32_t)(((uint64_t)(data)) & 0x00000000ffffffffU))
#define UINT64H_TO_UINT32(data) ((uint32_t)((((uint64_t)(data)) >> 32) & 0x00000000ffffffffU))
#define PKCS1_PADDING 0x01
#define NO_PADDING 0x02
#define MD5_PADDING 0x00
#define SHA1_PADDING 0x01
#define SHA256_PADDING 0x03
#define MD5_HASH_SZ 16
#define SHA1_HASH_SZ 20
#define SHA256_HASH_SZ 32
#define RAS_CALCULATE_Q 0x6
#define RSA_ENABLE_MODULE 0x3
#define RSA_ENDIAN_MODE 0x8
#define RSA_RESET 0x1
#define RSA_CAL_Q_DONE_OFFSET 0x5
typedef struct bignum {
uint32_t pdata[BN_MAX_WORDS];
uint32_t words;
} bignum_t;
typedef struct {
__IOM uint32_t rsa_mwid; /* Offset: 0x000 (R/W) Width of M register */
__IOM uint32_t rsa_ckid; /* Offset: 0x004 (R/W) Width of D register */
__IOM uint32_t rsa_bwid; /* Offset: 0x008 (R/W) Width of B register */
__IOM uint32_t rsa_ctrl; /* Offset: 0x00c (R/W) RSA control register */
__OM uint32_t rsa_rst; /* Offset: 0x010 (W) RSA reset register */
__IM uint32_t rsa_lp_cnt; /* Offset: 0x014 (R) Loop counter for inquiry register*/
__IM uint32_t rsa_q0; /* Offset: 0x018 (R) High-radix MM algorithm assistant register,part 1*/
__IM uint32_t rsa_q1; /* Offset: 0x01c (R) High-radix MM algorithm assistant register,part 2*/
__IOM uint32_t rsa_isr; /* Offset: 0x020 (W/R) Interrupt raw status register */
__IOM uint32_t rsa_imr; /* Offset: 0x024 (W/R) Interrupt mask register */
__IOM uint32_t rev1[54]; /* Reserve regiser */
__IOM uint32_t rsa_rfm; /* Offset: 0x100 (W/R) Register file for modulus M */
__IOM uint32_t rev2[63]; /* Reserve regiser */
__IOM uint32_t rsa_rfd; /* Offset: 0x200 (W/R) Register file for exponent D */
__IOM uint32_t rev3[63]; /* Reserve regiser */
__IOM uint32_t rsa_rfc; /* Offset: 0x300 (W/R) Register file for hard C */
__IOM uint32_t rev4[63]; /* Reserve regiser */
__IOM uint32_t rsa_rfb; /* Offset: 0x400 (W/R) Register file for data B */
__IOM uint32_t rev5[63]; /* Reserve regiser */
__IM uint32_t rsa_rfr; /* Offset: 0x500 (R) Register file for storing the result */
} ck_rsa_reg_t;
#endif

View file

@ -0,0 +1,44 @@
/*
* Copyright (C) 2017 C-SKY Microsystems Co., Ltd. All rights reserved.
*
* 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 ck_rtc.h
* @brief header file for rtc driver
* @version V1.0
* @date 02. June 2017
******************************************************************************/
#ifndef __CK_RTC_H
#define __CK_RTC_H
#include <stdio.h>
#include "soc.h"
#define SEC_PER_MIN ((time_t)60)
#define SEC_PER_HOUR ((time_t)60 * SEC_PER_MIN)
#define SEC_PER_DAY ((time_t)24 * SEC_PER_HOUR)
typedef struct {
__IM uint32_t RTC_CCVR; /* Offset: 0x000 (R/ ) current count value register */
__IOM uint32_t RTC_CMR; /* Offset: 0x004 (R/W) count match register */
__IOM uint32_t RTC_CLR; /* Offset: 0x008 (R/W) count load register */
__IOM uint32_t RTC_CCR; /* Offset: 0x00c (R/W) count control register */
__IM uint32_t RTC_STAT; /* Offset: 0x010 (R/ ) interrupt status register */
__IM uint32_t RTC_RSTAT; /* Offset: 0x014 (R/ ) interrupt raw status register */
__IM uint32_t RTC_EOI; /* Offset: 0x018 (R/ ) end of interrupt register */
__IM uint32_t RTC_COMP_VERSION; /* Offset: 0x01c (R/ ) component version register */
} ck_rtc_reg_t;
#endif /* __CK_RTC_H */

View file

@ -0,0 +1,75 @@
/*
* Copyright (C) 2017 C-SKY Microsystems Co., Ltd. All rights reserved.
*
* 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 ck_sasc_v1.h
* @brief head file for ck sasc v1
* @version V1.0
* @date 02. June 2017
******************************************************************************/
#ifndef _CK_SASC_H_
#define _CK_SASC_H_
#include "drv_sasc.h"
#include "soc.h"
#define REGION_USED 1
#define EFLASH_ADDR_START 0x10000000
#define EFLASH_ADDR_END 0x1003f7ff
#define EFLASH_SECTOR_SIZE 0x200
#define EFLASH_REG_BASE 0x4003f000
#define EFLASH_CAR 0x38
#define EFLASH_CR 0x3C
#define EFLASH_RG0 0x40
#define EFLASH_RG1 0x44
#define EFLASH_RG2 0x48
#define EFLASH_RG3 0x4C
#define EFLASH_RG4 0x50
#define EFLASH_RG5 0x54
#define EFLASH_RG6 0x58
#define EFLASH_RG7 0x5C
#define EFLASH_CFG0 0x60
#define EFLASH_CFG1 0x64
#define IS_EFLASH_ADDR(addr) \
((addr >= EFLASH_ADDR_START) && (addr <= EFLASH_ADDR_END))
#define SRAM_REG_BASE 0x40007000
#define SRAM_CAR 0x00
#define SRAM_CR 0x04
#define SRAM_RG0 0x08
#define SRAM_RG1 0x0c
#define SRAM_RG2 0x10
#define SRAM_RG3 0x14
#define SRAM_RG4 0x18
#define SRAM_RG5 0x1c
#define SRAM_RG6 0x20
#define SRAM_RG7 0x24
#define SRAM_CFG0 0x28
#define SRAM_CFG1 0x2c
#define SRAM_ADDR_START 0x60000000
#define SRAM_ADDR_END 0x60014000
#define IS_SRAM_ADDR(addr) \
((addr >= SRAM_ADDR_START) && (addr <= SRAM_ADDR_END))
#define REGION_MAX_NUM 8
#endif

View file

@ -0,0 +1,90 @@
/*
* Copyright (C) 2017 C-SKY Microsystems Co., Ltd. All rights reserved.
*
* 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 ck_sasc_v2.h
* @brief head file for ck sasc
* @version V1.0
* @date 02. June 2017
******************************************************************************/
#ifndef _CK_SASC_H_
#define _CK_SASC_H_
#include "drv_sasc.h"
#include "soc.h"
#define REGION_USED 1
#define EFLASH_ADDR_START 0x10000000
#define EFLASH_ADDR_END 0x1003f7ff
#define EFLASH_SECTOR_SIZE 0x200
#define EFLASH_REG_BASE 0x40005000
#define EFLASH_CAR 0x38
#define EFLASH_CR 0x3C
#define EFLASH_RG0 0x40
#define EFLASH_RG1 0x44
#define EFLASH_RG2 0x48
#define EFLASH_RG3 0x4C
#define EFLASH_RG4 0x50
#define EFLASH_RG5 0x54
#define EFLASH_RG6 0x58
#define EFLASH_RG7 0x5C
#define EFLASH_CFG0 0x60
#define EFLASH_CFG1 0x64
#define IS_EFLASH_ADDR(addr) \
((addr >= EFLASH_ADDR_START) && (addr <= EFLASH_ADDR_END))
#define SRAM_CAR 0x00
#define SRAM_CR 0x04
#define SRAM_RG0 0x08
#define SRAM_RG1 0x0c
#define SRAM_RG2 0x10
#define SRAM_RG3 0x14
#define SRAM_RG4 0x18
#define SRAM_RG5 0x1c
#define SRAM_RG6 0x20
#define SRAM_RG7 0x24
#define SRAM_CFG0 0x28
#define SRAM_CFG1 0x2c
#define SRAM_ADDR_START 0x20000000
#define SRAM_ADDR_END 0x2000ffff
#define SRAM0_ADDR_START 0x20000000
#define SRAM0_ADDR_END 0x20003fff
#define SRAM1_ADDR_START 0x20004000
#define SRAM1_ADDR_END 0x20007fff
#define SRAM2_ADDR_START 0x20008000
#define SRAM2_ADDR_END 0x2000ffff
#define IS_SRAM_ADDR(addr) \
((addr >= SRAM_ADDR_START) && (addr <= SRAM_ADDR_END))
#define IS_SRAM0_ADDR(addr) \
((addr >= SRAM0_ADDR_START) && (addr <= SRAM0_ADDR_END))
#define IS_SRAM1_ADDR(addr) \
((addr >= SRAM1_ADDR_START) && (addr <= SRAM1_ADDR_END))
#define IS_SRAM2_ADDR(addr) \
((addr >= SRAM2_ADDR_START) && (addr <= SRAM2_ADDR_END))
#define REGION_MAX_NUM 8
#endif

View file

@ -0,0 +1,61 @@
/*
* Copyright (C) 2017 C-SKY Microsystems Co., Ltd. All rights reserved.
*
* 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 ck_sha_v1.h
* @brief header file for sha driver
* @version V1.0
* @date 02. June 2017
******************************************************************************/
#ifndef _CK_SHA_H_
#define _CK_SHA_H_
#include <stdio.h>
#include "drv_sha.h"
#include "soc.h"
#define SHA_INIT_OFFSET 3
#define SHA_INT_ENABLE_OFFSET 4
#define SHA_ENDIAN_OFFSET 5
#define SHA_CAL_OFFSET 6
typedef struct {
__IOM uint32_t SHA_CON; /* Offset: 0x000 (R/W) Control register */
__IOM uint32_t SHA_MODE; /* Offset: 0x004 (R/W) Mode register */
__IOM uint32_t SHA_INTSTATE; /* Offset: 0x008 (R/W) Instatus register */
__IOM uint32_t SHA_BASEADDR; /* Offset: 0x00c (R/W) Baseaddr register */
__IOM uint32_t SHA_DESTADDR; /* Offset: 0x010 (R/W) Dest addr register */
__IOM uint32_t SHA_COUNTER0; /* Offset: 0x014 (R/W) count0 register */
__IOM uint32_t SHA_COUNTER1; /* Offset: 0x018 (R/W) count1 register */
__IOM uint32_t SHA_COUNTER2; /* Offset: 0x01c (R/W) count2 register */
__IOM uint32_t SHA_COUNTER3; /* Offset: 0x020 (R/W) count3 register */
__IOM uint32_t SHA_H0L; /* Offset: 0x024 (R/W) H0L register */
__IOM uint32_t SHA_H1L; /* Offset: 0x028 (R/W) H1L register */
__IOM uint32_t SHA_H2L; /* Offset: 0x02c (R/W) H2L register */
__IOM uint32_t SHA_H3L; /* Offset: 0x030 (R/W) H3L register */
__IOM uint32_t SHA_H4L; /* Offset: 0x034 (R/W) H4L register */
__IOM uint32_t SHA_H5L; /* Offset: 0x038 (R/W) H5L register */
__IOM uint32_t SHA_H6L; /* Offset: 0x03c (R/W) H6L register */
__IOM uint32_t SHA_H7L; /* Offset: 0x040 (R/W) H7L register */
__IOM uint32_t SHA_H0H; /* Offset: 0x044 (R/W) H0H register */
__IOM uint32_t SHA_H1H; /* Offset: 0x048 (R/W) H1H register */
__IOM uint32_t SHA_H2H; /* Offset: 0x04c (R/W) H2H register */
__IOM uint32_t SHA_H3H; /* Offset: 0x050 (R/W) H3H register */
__IOM uint32_t SHA_H4H; /* Offset: 0x054 (R/W) H4H register */
__IOM uint32_t SHA_H5H; /* Offset: 0x058 (R/W) H5H register */
__IOM uint32_t SHA_H6H; /* Offset: 0x05c (R/W) H6H register */
__IOM uint32_t SHA_H7H; /* Offset: 0x060 (R/W) H7H register */
} ck_sha_reg_t;
#endif

View file

@ -0,0 +1,63 @@
/*
* Copyright (C) 2017 C-SKY Microsystems Co., Ltd. All rights reserved.
*
* 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 ck_sha_v2.h
* @brief header file for sha driver
* @version V1.0
* @date 02. June 2017
******************************************************************************/
#ifndef _CK_SHA_H_
#define _CK_SHA_H_
#include <stdio.h>
#include "drv_sha.h"
#include "soc.h"
#define SHA_INIT_OFFSET 3
#define SHA_INT_ENABLE_OFFSET 4
#define SHA_ENDIAN_OFFSET 5
#define SHA_CAL_OFFSET 6
typedef struct {
__IOM uint32_t SHA_CON; /* Offset: 0x000 (R/W) Control register */
__IOM uint32_t SHA_INTSTATE; /* Offset: 0x004 (R/W) Instatus register */
__IOM uint32_t SHA_H0L; /* Offset: 0x008 (R/W) H0L register */
__IOM uint32_t SHA_H1L; /* Offset: 0x00c (R/W) H1L register */
__IOM uint32_t SHA_H2L; /* Offset: 0x010 (R/W) H2L register */
__IOM uint32_t SHA_H3L; /* Offset: 0x014 (R/W) H3L register */
__IOM uint32_t SHA_H4L; /* Offset: 0x018 (R/W) H4L register */
__IOM uint32_t SHA_H5L; /* Offset: 0x01c (R/W) H5L register */
__IOM uint32_t SHA_H6L; /* Offset: 0x020 (R/W) H6L register */
__IOM uint32_t SHA_H7L; /* Offset: 0x024 (R/W) H7L register */
__IOM uint32_t SHA_H0H; /* Offset: 0x028 (R/W) H0H register */
__IOM uint32_t SHA_H1H; /* Offset: 0x02c (R/W) H1H register */
__IOM uint32_t SHA_H2H; /* Offset: 0x030 (R/W) H2H register */
__IOM uint32_t SHA_H3H; /* Offset: 0x034 (R/W) H3H register */
__IOM uint32_t SHA_H4H; /* Offset: 0x038 (R/W) H4H register */
__IOM uint32_t SHA_H5H; /* Offset: 0x03c (R/W) H5H register */
__IOM uint32_t SHA_H6H; /* Offset: 0x040 (R/W) H6H register */
__IOM uint32_t SHA_H7H; /* Offset: 0x044 (R/W) H7H register */
__IOM uint32_t SHA_DATA1; /* Offset: 0x048 (R/W) DATA1 register */
uint32_t REV[15];
__IOM uint32_t SHA_DATA2; /* Offset: 0x088 (R/W) DATA2 register */
} ck_sha_reg_t;
#endif
typedef enum {
SHA_STATUS_START_END = 0, /* the one time count mode */
SHA_STATUS_START = 1, /* the first time of the cal */
SHA_STATUS_CONTINUE = 2, /* the middle stage of the cal */
SHA_STATUS_END = 3 /* the last time of the cal*/
} enum_sha_status;

View file

@ -0,0 +1,18 @@
#define getData(value,base,offset) value=*(volatile uint32_t *)(base+offset)
#define putData(value,base,offset) *(volatile uint32_t *)(base+offset)=value
#define GLOBAL_BASE 0x0
#define PROG_BASE 0x0100
#define INST_BASE 0x2100
#define PGPIO_BASE 0x6100
#define SPU_INST_RAM_SIZE 12288
#define SPU_PROG_RAM_SIZE 32768
#define OFFSET_PGPIO_CLK_EN 0x0
#define OFFSET_BLOCKS_CLK_EN 0x4
#define OFFSET_PGPIO_INTR_STATUS 0x8
#define OFFSET_PGPIO_INTR_SEL 0xC
#define OFFSET_PGPIO_START_EN 0x10
#define SPU_CLK_FREQUENCY 20000000

View file

@ -0,0 +1,84 @@
//======================================
//baud rate & filter
//======================================
#define I2C_FREQUENCY_STANDARD 10000
//#define I2C_FREQUENCY_FAST 400000
#define I2C_FREQUENCY_FAST 100000
#define I2C_FREQUENCY_FAST_PLUS 1000000
//#define I2C_FREQUENCY_HIGH 1000000
#define I2C_FREQUENCY_HIGH 200000
#define I2C_FILTER_COE 2
//======================================
//PROG_RAM offset
//======================================
#define I2C_OFFSET_REFER_CLK 0x0
#define I2C_OFFSET_CTRL 0x4
#define I2C_OFFSET_TRANS_LEN 0x8
#define I2C_OFFSET_INT 0xC
//======================================
//"CTRL" value
//======================================
//master mode
#define I2C_TX_CONTINUE 0x1
#define I2C_RX_CONTINUE 0x2
//#define I2C_TX_RESTART 0X4
//#define I2C_RX_RESTART 0X8
#define I2C_HS_FLAG 0x4
#define I2C_READ_FLAG 0x8
#define I2C_PEND_EN 0x10
#define I2C_SR_FLAG 0x20
//slave mode
#define I2C_SLV_BUSY 0x1
#define I2C_SLV_RX 0x2
//======================================
//"INTERRUPT" value
//======================================
#define I2C_INT_TX_EMPTY 0x1
#define I2C_INT_TX_NACK 0x2
#define I2C_INT_RX_FULL 0x4
#define I2C_INT_DONE 0x8
#define I2C_INT_PENDING 0x10
#define I2C_INT_ARB_LOST 0x20 //master mode
#define I2C_INT_GENE_CALL 0x20 //slave mode
#define I2C_INT_SLV_TX 0x40
#define I2C_INT_SLV_RX 0x80
//======================================
//configuration of TX/RX fifo
//======================================
//master mode
#define I2C_M_OFFSET_TX_HEAD_W0 0x10
#define I2C_M_OFFSET_TX_HEAD_W1 0x14
#define I2C_M_OFFSET_RX_HEAD_W0 0x18
#define I2C_M_OFFSET_RX_HEAD_W1 0x1C
#define I2C_M_OFFSET_FIFO_MEM_LITTLE (I2C_M_OFFSET_RX_HEAD_W1+0x4)
#define I2C_M_OFFSET_FIFO_MEM_BIG (I2C_M_OFFSET_FIFO_MEM_LITTLE+(I2C_M_FIFO_DEPTH_LITTLE+1)*4)
#define I2C_M_FIFO_DEPTH_LITTLE 3
#define I2C_M_FIFO_DEPTH_BIG 7
#define I2C_M_TX_EMPTY_TL 0
#define I2C_M_RX_FULL_TL 0
#define I2C_M_PROG_BYTES (I2C_M_OFFSET_FIFO_MEM_LITTLE+(I2C_M_FIFO_DEPTH_LITTLE+I2C_M_FIFO_DEPTH_BIG+2)*4)
//slave mode
#define I2C_S_OFFSET_FIFO_HEAD_W0 0x10
#define I2C_S_OFFSET_FIFO_HEAD_W1 0x14
#define I2C_S_OFFSET_FIFO_MEM (I2C_S_OFFSET_FIFO_HEAD_W1+0x4)
#define I2C_S_FIFO_DEPTH 7
#define I2C_S_TX_EMPTY_TL 0
#define I2C_S_RX_FULL_TL 0
#define I2C_S_PROG_BYTES (I2C_S_OFFSET_FIFO_MEM+(I2C_S_FIFO_DEPTH+1)*4)
//======================================
//RESTART flag in data
//======================================
#define I2C_SR_IN_DATA 0x80000000

View file

@ -0,0 +1,48 @@
//======================================
//baud rate & filter
//======================================
#define SPI_FILTER_COE 2
//======================================
//PROG_RAM offset
//======================================
#define SPI_OFFSET_REFER_CLK 0x0
#define SPI_OFFSET_CTRL 0x4
#define SPI_OFFSET_DEFAULT_VALUE 0x8
#define SPI_OFFSET_TRANS_LEN 0xC
#define SPI_OFFSET_INT 0x10
#define SPI_OFFSET_TX_HEAD_W0 0x14
#define SPI_OFFSET_TX_HEAD_W1 0x18
#define SPI_OFFSET_RX_HEAD_W0 0x1C
#define SPI_OFFSET_RX_HEAD_W1 0x20
//======================================
//"CTRL" value
//======================================
#define SPI_TMOD_TRANSMIT 0x1
#define SPI_TMOD_RECEIVE 0x2
#define SPI_TMOD_TRANSFER 0x3
#define SPI_BACK_TO_BACK 0x4
#define SPI_CS_PEND 0x8
//======================================
//"INTERRUPT" value
//======================================
#define SPI_INT_RX_DONE 0x1
#define SPI_INT_RX_FULL 0x2
#define SPI_INT_TX_DONE 0x4
#define SPI_INT_TX_EMPTY 0x8
//======================================
//configuration of TX/RX fifo
//======================================
#define SPI_TX_FIFO_DEPTH 7
#define SPI_TX_FIFO_EMPTY_TL 1
#define SPI_RX_FIFO_DEPTH 7
#define SPI_RX_FIFO_FULL_TL 6
#define SPI_OFFSET_TX_MEM (SPI_OFFSET_RX_HEAD_W1+4)
#define SPI_OFFSET_RX_MEM (SPI_OFFSET_TX_MEM+(SPI_TX_FIFO_DEPTH+1)*4)
#define SPI_PROG_BYTES (SPI_OFFSET_RX_MEM+(SPI_RX_FIFO_DEPTH+1)*4)

View file

@ -0,0 +1,59 @@
/*
* Copyright (C) 2017 C-SKY Microsystems Co., Ltd. All rights reserved.
*
* 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 ck_spu_usart.h
* @brief header file for spu usart driver
* @version V1.0
* @date 02. June 2017
******************************************************************************/
#ifndef __DW_USART_H
#define __DW_USART_H
//======================================
//filter
//======================================
#define USART_FILTER_COE 2
//======================================
//PROG_RAM offset
//======================================
#define USART_OFFSET_CTRL 0x0
#define USART_OFFSET_TRANS_LEN 0x4
#define USART_OFFSET_INT 0x8
#define USART_OFFSET_FIFO_HEAD_W0 0xC
#define USART_OFFSET_FIFO_HEAD_W1 0x10
#define USART_OFFSET_FIFO_MEM 0x14
//======================================
//"INTERRUPT" value
//======================================
#define USART_INT_RX_DONE 0x1
#define USART_INT_RX_FULL 0x2
#define USART_INT_TX_DONE 0x4
#define USART_INT_TX_EMPTY 0x8
#define USART_INT_PARITY_ERR 0x10
#define USART_INT_STOP_ERR 0x20
//======================================
//configuration of TX/RX fifo
//======================================
#define USART_FIFO_DEPTH 7
#define USART_FIFO_EMPTY_TL 1
#define USART_FIFO_FULL_TL 6
#define USART_PROG_BYTES (USART_OFFSET_FIFO_MEM+(USART_FIFO_DEPTH+1)*4)
#endif /* __DW_USART_H */

View file

@ -0,0 +1,40 @@
/*
* Copyright (C) 2017 C-SKY Microsystems Co., Ltd. All rights reserved.
*
* 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 ck_trng.h
* @brief header file for trng driver
* @version V1.0
* @date 02. June 2017
******************************************************************************/
#ifndef _CK_TRNG_H_
#define _CK_TRNG_H_
#include "drv_trng.h"
#include "soc.h"
/*
* define the bits for TCR
*/
#define TRNG_EN (1UL << 1)
#define TRNG_LOWPER_MODE (1UL << 2)
#define TRNG_DATA_READY 1
typedef struct {
__IOM uint32_t TCR; /* Offset: 0x000 (W/R) TRNG control register */
__IM uint32_t TDR; /* Offset: 0x004 (R) TRNG Data register */
} ck_trng_reg_t;
#endif

View file

@ -0,0 +1,89 @@
/*
* Copyright (C) 2017 C-SKY Microsystems Co., Ltd. All rights reserved.
*
* 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 ck_usart.h
* @brief header file for usart driver
* @version V1.0
* @date 02. June 2017
******************************************************************************/
#ifndef __CK_USART_H
#define __CK_USART_H
#include <stdio.h>
#include "errno.h"
#include "soc.h"
#define BAUDRATE_DEFAULT 19200
#define UART_BUSY_TIMEOUT 1000000
#define UART_RECEIVE_TIMEOUT 1000
#define UART_TRANSMIT_TIMEOUT 1000
#define UART_MAX_FIFO 0x10
/* UART register bit definitions */
#define USR_UART_BUSY 0x01
#define USR_UART_TFE 0x04
#define USR_UART_RFNE 0x08
#define LSR_DATA_READY 0x01
#define LSR_THR_EMPTY 0x20
#define IER_RDA_INT_ENABLE 0x01
#define IER_THRE_INT_ENABLE 0x02
#define IIR_NO_ISQ_PEND 0x01
#define LCR_SET_DLAB 0x80 /* enable r/w DLR to set the baud rate */
#define LCR_PARITY_ENABLE 0x08 /* parity enabled */
#define LCR_PARITY_EVEN 0x10 /* Even parity enabled */
#define LCR_PARITY_ODD 0xef /* Odd parity enabled */
#define LCR_WORD_SIZE_5 0xfc /* the data length is 5 bits */
#define LCR_WORD_SIZE_6 0x01 /* the data length is 6 bits */
#define LCR_WORD_SIZE_7 0x02 /* the data length is 7 bits */
#define LCR_WORD_SIZE_8 0x03 /* the data length is 8 bits */
#define LCR_STOP_BIT1 0xfb /* 1 stop bit */
#define LCR_STOP_BIT2 0x04 /* 1.5 stop bit */
#define DW_LSR_PFE 0x80
#define DW_LSR_TEMT 0x40
#define DW_LSR_THRE 0x40
#define DW_LSR_BI 0x10
#define DW_LSR_FE 0x08
#define DW_LSR_PE 0x04
#define DW_LSR_OE 0x02
#define DW_LSR_DR 0x01
#define DW_LSR_TRANS_EMPTY 0x20
#define DW_IIR_THR_EMPTY 0x02 /* threshold empty */
#define DW_IIR_RECV_DATA 0x04 /* received data available */
typedef struct {
union {
__IM uint32_t RBR; /* Offset: 0x000 (R/ ) Receive buffer register */
__OM uint32_t THR; /* Offset: 0x000 ( /W) Transmission hold register */
__IOM uint32_t DLL; /* Offset: 0x000 (R/W) Clock frequency division low section register */
};
union {
__IOM uint32_t DLH; /* Offset: 0x004 (R/W) Clock frequency division high section register */
__IOM uint32_t IER; /* Offset: 0x004 (R/W) Interrupt enable register */
};
__IM uint32_t IIR; /* Offset: 0x008 (R/ ) Interrupt indicia register */
__IOM uint32_t LCR; /* Offset: 0x00C (R/W) Transmission control register */
uint32_t RESERVED0;
__IM uint32_t LSR; /* Offset: 0x014 (R/ ) Transmission state register */
__IM uint32_t MSR; /* Offset: 0x018 (R/ ) Modem state register */
uint32_t RESERVED1[24];
__IM uint32_t USR; /* Offset: 0x07c (R/ ) UART state register */
} dw_usart_reg_t;
#endif /* __CK_USART_H */

View file

@ -0,0 +1,137 @@
/*
* Copyright (C) 2017 C-SKY Microsystems Co., Ltd. All rights reserved.
*
* 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 dw_dmac.h
* @brief header file for DMAC Driver
* @version V1.0
* @date 02. June 2017
******************************************************************************/
#ifndef __CK_DMA_H
#define __CK_DMA_H
#include <stdio.h>
#include "soc.h"
#define CK_DMA_MAXCHANNEL 2
#define CK_DMA_INT_EN 1
#define CK_DMA_CH_EN 1
#define CK_DMA_TFR 0x0002
#define CK_DMA_ERR 0x0001
#define CK_DMA_INTC 0x1f
#define CK_DMA_MASK 0x1f00
typedef enum {
DMA_ADDR_INCREMENT = 0,
DMA_ADDR_DECREMENT = 1,
DMA_ADDR_NOCHANGE = 2
} enum_addr_state_e;
typedef enum {
DMA_DATAWIDTH_SIZE8 = 1,
DMA_DATAWIDTH_SIZE16 = 2,
DMA_DATAWIDTH_SIZE32 = 4
} dma_datawidth_e;
typedef enum {
DMA_HANDSHAKING_HARDWARE = 0,
DMA_HANDSHAKING_SOFTWARE = 1,
} dma_handshaking_select_e;
typedef enum {
DMA_PRIORITY0 = 0,
DMA_PRIORITY1 = 1,
DMA_PRIOTITY2 = 2,
DMA_PRIOTITY3 = 3
} dma_priority_t;
typedef enum {
DWENUM_DMA_UART0_RX,
DWENUM_DMA_UART0_TX,
DWENUM_DMA_UART1_RX,
DWENUM_DMA_UART1_TX,
DWENUM_DMA_SPI0_RX,
DWENUM_DMA_SPI0_TX,
DWENUM_DMA_SPI1_RX,
DWENUM_DMA_SPI1_TX,
DWENUM_DMA_IIC_RX,
DWENUM_DMA_IIC_TX,
DWENUM_DMA_ADC_RX,
DWENUM_DMA_ADC_TX,
DWENUM_DMA_IIC1_RX,
DWENUM_DMA_IIC1_TX,
DWENUM_DMA_IIS_RX,
DWENUM_DMA_IIS_TX,
DWENUM_DMA_MEMORY
} dwenum_dma_device_e;
#define DMA_REG_SARx 0x0
#define DMA_REG_DARx 0x8
#define DMA_REG_CTRLax 0x18
#define DMA_REG_CTRLbx 0x1c
#define DMA_REG_CFGax 0x40
#define DMA_REG_CFGbx 0x44
#define DMA_REG_RawTfr 0x2c0
#define DMA_REG_RawBlock 0x2c8
#define DMA_REG_RawSrcTran 0x2d0
#define DMA_REG_RawDstTran 0x2d8
#define DMA_REG_RawErr 0x2e0
#define DMA_REG_StatusTfr 0x2e8
#define DMA_REG_StatusBlock 0x2f0
#define DMA_REG_StatusSrcTran 0x2f8
#define DMA_REG_StatusDstTran 0x300
#define DMA_REG_StatusErr 0x308
#define DMA_REG_MaskTfr 0x310
#define DMA_REG_MaskBlock 0x318
#define DMA_REG_MaskSrcTran 0x320
#define DMA_REG_MaskDstTran 0x328
#define DMA_REG_MaskErr 0x330
#define DMA_REG_ClearTfr 0x338
#define DMA_REG_ClearBlock 0x340
#define DMA_REG_ClearSrcTran 0x348
#define DMA_REG_ClearDstTran 0x350
#define DMA_REG_ClearErr 0x358
#define DMA_REG_StatusInt 0x360
#define DMA_REG_ReqSrc 0x368
#define DMA_REG_ReqDst 0x370
#define DMA_REG_SglReqSrc 0x378
#define DMA_REG_SglReqDst 0x380
#define DMA_REG_LstReqSrc 0x388
#define DMA_REG_LstReqDst 0x390
#define DMA_REG_Cfg 0x398
#define DMA_REG_ChEn 0x3a0
//typedef struct {
// __IOM uint32_t SAR; /* offset: 0x00 (R/W) Channel Source Address Register */
// __IOM uint32_t DAR; /* offset: 0x04 (R/W) Channel Destination Address Register */
// __IOM uint32_t CHCTRLA; /* offset: 0x08 (R/W) Channel Control Register A */
// __IOM uint32_t CHCTRLB; /* offset: 0x0C (R/W) Channel Control Register B */
// __IOM uint8_t CHINTM:2; /* offset: 0x10 (R/W) Channel Interrupt Mask Register */
// uint8_t RESERVED0[3];
// __IM uint8_t CHINTS:2; /* offset: 0x14 (R/ ) Channel Interrupt Status Register */
// uint8_t RESERVED1[3];
// __IOM uint8_t CHINTC:2; /* offset: 0x18 (R/W) Channel Interrupt Clear Register */
// uint8_t RESERVED2[3];
// __IOM uint8_t CHSREQ:1; /* offset: 0x1C (R/W) Channel Software Request Register */
// uint8_t RESERVED3[3];
// __IOM uint8_t CHEN:1; /* offset: 0x20 (R/W) Channel Enable Register */
// uint8_t RESERVED4[3];
//} dw_dma_reg_t;
#endif /* __CK_DMA_H */

View file

@ -0,0 +1,54 @@
/*
* Copyright (C) 2017 C-SKY Microsystems Co., Ltd. All rights reserved.
*
* 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 dw_gpio.h
* @brief header file for GPIO Driver
* @version V1.0
* @date 02. June 2017
******************************************************************************/
#ifndef _DW_GPIO_H_
#define _DW_GPIO_H_
#include "drv_gpio.h"
#include "soc.h"
typedef struct {
__IOM uint32_t SWPORT_DR; /* Offset: 0x000 (W/R) PortA data register */
__IOM uint32_t SWPORT_DDR; /* Offset: 0x004 (W/R) PortA data direction register */
__IOM uint32_t PORT_CTL; /* Offset: 0x008 (W/R) PortA source register */
} dw_gpio_reg_t;
typedef struct {
__IOM uint32_t INTEN; /* Offset: 0x000 (W/R) Interrupt enable register */
__IOM uint32_t INTMASK; /* Offset: 0x004 (W/R) Interrupt mask register */
__IOM uint32_t INTTYPE_LEVEL; /* Offset: 0x008 (W/R) Interrupt level register */
__IOM uint32_t INT_POLARITY; /* Offset: 0x00c (W/R) Interrupt polarity register */
__IM uint32_t INTSTATUS; /* Offset: 0x010 (R) Interrupt status of Port */
__IM uint32_t RAWINTSTATUS; /* Offset: 0x014 (W/R) Raw interrupt status of Port */
__IOM uint32_t revreg1; /* Offset: 0x018 (W/R) Reserve register */
__OM uint32_t PORTA_EOI; /* Offset: 0x01c (W/R) Port clear interrupt register */
__IM uint32_t EXT_PORTA; /* Offset: 0x020 (W/R) PortA external port register */
__IM uint32_t EXT_PORTB; /* Offset: 0x024 (W/R) PortB external port register */
__IOM uint32_t revreg2[2]; /* Offset: 0x028 (W/R) Reserve register */
__IOM uint32_t LS_SYNC; /* Offset: 0x030 (W/R) Level-sensitive synchronization enable register */
} dw_gpio_control_reg_t;
#endif

View file

@ -0,0 +1,129 @@
/*
* Copyright (C) 2017 C-SKY Microsystems Co., Ltd. All rights reserved.
*
* 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 dw_iic.h
* @brief header File for IIC Driver
* @version V1.0
* @date 02. June 2017
******************************************************************************/
#ifndef __DW_IIC_H
#define __DW_IIC_H
#include "soc.h"
/*
* Define the speed of I2C
*/
typedef enum {
DW_IIC_STANDARDSPEED = 1,
DW_IIC_FASTSPEED = 2,
DW_IIC_HIGHSPEED = 3
} DWENUM_IIC_SPEED;
enum i2c_state_e {
IIC_STATE_NONE = 0, /* Send start + (first part of) address. */
IIC_STATE_DATASEND, /* Send data. */
IIC_STATE_WFDATA, /* Wait for data. */
IIC_STATE_WFSTOPSENT, /* Wait for STOP to have been transmitted. */
IIC_STATE_DONE, /* Transfer completed successfully. */
IIC_STATE_SEND_DONE, /* send completed successfully. */
IIC_STATE_RECV_DONE, /* receive completed successfully. */
IIC_STATE_ERROR /* Transfer error. */
};
/*
* Define the interrupt type of I2C
*/
#define DW_IIC_INTR_RX_UNDER 0x001
#define DW_IIC_INTR_RX_OVER 0x002
#define DW_IIC_INTR_RX_FULL 0x004
#define DW_IIC_INTR_TX_OVER 0x008
#define DW_IIC_INTR_TX_EMPTY 0x010
#define DW_IIC_INTR_RD_REQ 0x020
#define DW_IIC_INTR_TX_ABRT 0x040
#define DW_IIC_INTR_RX_DONE 0x080
#define DW_IIC_INTR_ACTIVITY 0x100
#define DW_IIC_INTR_STOP_DET 0x200
#define DW_IIC_INTR_START_DET 0x400
#define DW_IIC_INTR_GEN_CALL 0x800
#define DW_IIC_INTR_DEFAULT_MASK (DW_IIC_INTR_RX_FULL | \
DW_IIC_INTR_TX_EMPTY | \
DW_IIC_INTR_TX_ABRT | \
DW_IIC_INTR_STOP_DET)
/*
* I2C register bit definitions
*/
#define DW_IIC_DISABLE 0
#define DW_IIC_ENABLE 1
#define DW_IIC_FIFO_MAX_LV 0x8
#define DW_IIC_TXFIFO_LV 0x0
#define DW_IIC_RXFIFO_LV 0x0
#define DW_IIC_RXFIFO_FULL (0x1 << 4)
#define DW_IIC_RXFIFO_NOT_EMPTY (0x1 << 3)
#define DW_IIC_TXFIFO_EMPTY (0x1 << 2)
#define DW_IIC_TXFIFO_NOT_FULL (0x1 << 1)
#define DW_IIC_STATUS_ACTIVITY 0x1
#define DW_IIC_FIFO_RST_EN 0x01
#define DW_IIC_CON_DEFAUL 0x23
typedef struct {
__IOM uint32_t IC_CON; /* Offset: 0x000 (R/W) Receive buffer register */
__IOM uint32_t IC_TAR; /* Offset: 0x004 (R/W) Transmission hold register */
__IOM uint32_t IC_SAR; /* Offset: 0x008 (R/W) Clock frequency division low section register */
__IOM uint32_t IC_HS_MADDR; /* Offset: 0x00c (R/W) Clock frequency division high section register */
__IOM uint32_t IC_DATA_CMD; /* Offset: 0x010 (R/W) Interrupt enable register */
__IOM uint32_t IC_SS_SCL_HCNT; /* Offset: 0x014 (R/W) Interrupt indicia register */
__IOM uint32_t IC_SS_SCL_LCNT; /* Offset: 0x018 (R/W) Transmission control register */
__IOM uint32_t IC_FS_SCL_HCNT; /* Offset: 0x01c (R/W) Modem control register */
__IOM uint32_t IC_FS_SCL_LCNT; /* Offset: 0x020 (R/W) Fast speed I2C Clock SCL Low Count */
__IOM uint32_t IC_HS_SCL_HCNT; /* Offset: 0x024 (R/W) High speed I2C Clock SCL High Count*/
__IOM uint32_t IC_HS_SCL_LCNT; /* Offset: 0x028 (R/W) High speed I2C Clock SCL Low Count */
__IM uint32_t IC_INTR_STAT; /* Offset: 0x02c (R) I2C Interrupt Status */
__IOM uint32_t IC_INTR_MASK; /* Offset: 0x030 (R/W) I2C Interrupt Mask */
__IM uint32_t IC_RAW_INTR_STAT; /* Offset: 0x034 (R) I2C Raw Interrupt Status */
__IOM uint32_t IC_RX_TL; /* Offset: 0x038 (R/W) I2C Receive FIFO Threshold */
__IOM uint32_t IC_TX_TL; /* Offset: 0x03c (R/W) I2C Transmit FIFO Threshold */
__IM uint32_t IC_CLR_INTR; /* Offset: 0x040 (R) Clear combined and individual interrupts*/
__IM uint32_t IC_CLR_RX_UNDER; /* Offset: 0x044 (R) I2C Clear RX_UNDER interrupt */
__IM uint32_t IC_CLR_RX_OVER; /* Offset: 0x048 (R) I2C Clear RX_OVER interrupt */
__IM uint32_t IC_CLR_TX_OVER; /* Offset: 0x04c (R) I2C Clear TX_OVER interrupt */
__IM uint32_t IC_CLR_RD_REQ; /* Offset: 0x050 (R) I2C Clear RD_REQ interrupt */
__IM uint32_t IC_CLR_TX_ABRT; /* Offset: 0x054 (R) I2C Clear TX_ABRT interrupt */
__IM uint32_t IC_CLR_RX_DONE; /* Offset: 0x058 (R) I2C Clear RX_DONE interrupt */
__IM uint32_t IC_CLR_ACTIVITY; /* Offset: 0x05c (R) I2C Clear ACTIVITY interrupt */
__IM uint32_t IC_CLR_STOP_DET; /* Offset: 0x060 (R) I2C Clear STOP_DET interrupt */
__IM uint32_t IC_CLR_START_DET; /* Offset: 0x064 (R) I2C Clear START_DET interrupt */
__IM uint32_t IC_CLR_GEN_CALL; /* Offset: 0x068 (R) I2C Clear GEN_CAL interrupt */
__IOM uint32_t IC_ENABLE; /* Offset: 0x06c (R/W) I2C enable */
__IM uint32_t IC_STATUS; /* Offset: 0x070 (R) I2C status register */
__IM uint32_t IC_TXFLR; /* Offset: 0x074 (R) Transmit FIFO Level register */
__IM uint32_t IC_RXFLR; /* Offset: 0x078 (R) Receive FIFO Level Register */
uint32_t RESERVED; /* Offset: 0x07c (R/ ) */
__IOM uint32_t IC_TX_ABRT_SOURCE; /* Offset: 0x080 (R/W) I2C Transmit Abort Status Register */
__IOM uint32_t IC_SAR1; /* Offset: 0x084 (R/W) I2C Slave Address1 */
__IOM uint32_t IC_DMA_CR; /* Offset: 0x088 (R/W) DMA Control Register for transmit and receive handshaking interface */
__IOM uint32_t IC_DMA_TDLR; /* Offset: 0x08c (R/W) DMA Transmit Data Level */
__IOM uint32_t IC_DMA_RDLR; /* Offset: 0x090 (R/W) DMA Receive Data Level */
__IOM uint32_t IC_SAR2; /* Offset: 0x094 (R/W) I2C Slave Address2 */
__IOM uint32_t IC_SAR3; /* Offset: 0x098 (R/W) I2C Slave Address3 */
__IOM uint32_t IC_MULTI_SLAVE; /* Offset: 0x09c (R/W) I2C address number in slave mode */
__IOM uint32_t IC_GEN_CALL_EN; /* Offset: 0x0a0 (R/W) I2C general call mask register when I2C is in the slave mode */
__IOM uint32_t IC_FIFO_RST_EN; /* Offset: 0x0a4 (R/W) I2C FIFO flush register when I2C is in the slave transfer mode*/
} dw_iic_reg_t;
#endif /* __DW_IIC_H */

View file

@ -0,0 +1,159 @@
/*
* Copyright (C) 2017 C-SKY Microsystems Co., Ltd. All rights reserved.
*
* 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 dw_spi.h
* @brief header file for spi driver
* @version V1.0
* @date 02. June 2017
******************************************************************************/
#ifndef __DW_SPI_H
#define __DW_SPI_H
#include <stdio.h>
#include "soc.h"
/*
* SPI register bit definitions
*/
#define DW_SPI_ENABLE 0x01
#define DW_SPI_DISABLE 0x00
#define DW_SPI_TMOD_BIT8 0x0100
#define DW_SPI_TMOD_BIT9 0x0200
#define DW_SPI_POLARITY 0x80
#define DW_SPI_PHASE 0x40
#define DW_SPI_BUSY 0x01
#define DW_SPI_TFE 0x04
#define DW_SPI_RFNE 0x08
#define DW_SPI_INT_EN 0x19
#define DW_SPI_RINT_EN 0x3e
#define DW_SPI_TINT_EN 0x3f
#define DW_SPI_INT_DISABLE 0x00
#define DW_SPI_INT_MASK_RX 0x27
#define DW_SPI_INT_MASKTX 0x3e
#define DW_SPI_RDMAE 0x1
#define DW_SPI_TDMAE 0x2
#define DW_SPI_TXFIFO_LV 0x0
#define DW_SPI_RXFIFO_LV 0x1d
#define DW_SPI_RXFIFO_NOT_EMPTY 0x08
#define DW_SPI_START_RX 0x0
#define DW_SPI_FIFO_MAX_LV 0x20
#define DW_SPI_FIFO_OVER_LV 0x18
#define DW_SPI_RXFIFO_OVERFLOW 0x08
#define DW_SPI_RXFIFO_FULL 0x10
#define DW_SPI_TXFIFO_EMPTY 0x01
#define SPI_CS_SELECTED 0x0
#define DW_SPI_IMR_TXEIM 0x01 /* Transmit FIFO Empty Interrupt Mask */
#define DW_SPI_IMR_RXFIM 0x10 /* Receive FIFO Full Interrupt Mask */
/* some infoermationgs of SPI for special MCU */
#define DW_SPI_DEFAULT_BAUDR 10000000 /* 10M */
#define DW_SPI_MAXID 0x1
#define SPI_INITIALIZED ((uint8_t)(1U)) // SPI initalized
#define SPI_POWERED ((uint8_t)(1U<< 1)) // SPI powered on
#define SPI_CONFIGURED ((uint8_t)(1U << 2)) // SPI configured
#define SPI_DATA_LOST ((uint8_t)(1U << 3)) // SPI data lost occurred
#define SPI_MODE_FAULT ((uint8_t)(1U << 4)) // SPI mode fault occurred
typedef enum {
DWENUM_SPI_DMACR_RXE = 0,
DWENUM_SPI_DMACR_TXE = 1,
} DWENUM_SPI_DMACR;
typedef enum {
DWENUM_SPI_TXRX = 0,
DWENUM_SPI_TX = 1,
DWENUM_SPI_RX = 2,
DWENUM_SPI_EERX = 3
} DWENUM_SPI_MODE;
typedef enum {
DWENUM_SPI_CLOCK_POLARITY_LOW = 0,
DWENUM_SPI_CLOCK_POLARITY_HIGH = 1
} DWENUM_SPI_POLARITY;
typedef enum {
DWENUM_SPI_CLOCK_PHASE_MIDDLE = 0,
DWENUM_SPI_CLOCK_PHASE_START = 1
} DWENUM_SPI_PHASE;
typedef enum {
DWENUM_SPI_DATASIZE_4 = 3,
DWENUM_SPI_DATASIZE_5 = 4,
DWENUM_SPI_DATASIZE_6 = 5,
DWENUM_SPI_DATASIZE_7 = 6,
DWENUM_SPI_DATASIZE_8 = 7,
DWENUM_SPI_DATASIZE_9 = 8,
DWENUM_SPI_DATASIZE_10 = 9,
DWENUM_SPI_DATASIZE_11 = 10,
DWENUM_SPI_DATASIZE_12 = 11,
DWENUM_SPI_DATASIZE_13 = 12,
DWENUM_SPI_DATASIZE_14 = 13,
DWENUM_SPI_DATASIZE_15 = 14,
DWENUM_SPI_DATASIZE_16 = 15
} DWENUM_SPI_DATAWIDTH;
typedef enum {
DWENUM_SPI_CS0 = 1,
DWENUM_SPI_CS1 = 2
} DWENUM_SPI_SLAVE;
typedef struct {
__IOM uint16_t CTRLR0; /* Offset: 0x000 (R/W) Control register 0 */
uint16_t RESERVED0;
__IOM uint16_t CTRLR1; /* Offset: 0x004 (R/W) Control register 1 */
uint16_t RESERVED1;
__IOM uint8_t SPIENR; /* Offset: 0x008 (R/W) SSI enable regiseter */
uint8_t RESERVED2[7];
__IOM uint32_t SER; /* Offset: 0x010 (R/W) Slave enable register */
__IOM uint16_t BAUDR; /* Offset: 0x014 (R/W) Baud rate select */
uint16_t RESERVED3;
__IOM uint32_t TXFTLR; /* Offset: 0x018 (R/W) Transmit FIFO Threshold Level */
__IOM uint32_t RXFTLR; /* Offset: 0x01c (R/W) Receive FIFO Threshold Level */
__IOM uint32_t TXFLR; /* Offset: 0x020 (R/W) Transmit FIFO Level register */
__IOM uint32_t RXFLR; /* Offset: 0x024 (R/W) Receive FIFO Level Register */
__IOM uint8_t SR; /* Offset: 0x028 (R/W) status register */
uint8_t RESERVED4[3];
__IOM uint32_t IMR; /* Offset: 0x02C (R/W) Interrupt Mask Register */
__IM uint32_t ISR; /* Offset: 0x030 (R/W) interrupt status register */
__IM uint32_t RISR; /* Offset: 0x034 (R/W) Raw Interrupt Status Register */
__IM uint8_t TXOICR; /* Offset: 0x038 (R/W) Transmit FIFO Overflow Interrupt Clear Register */
uint8_t RESERVED5[3];
__IM uint8_t RXOICR; /* Offset: 0x03C (R/W) Receive FIFO Overflow Interrupt Clear Register*/
uint8_t RESERVED6[3];
__IM uint8_t RXUICR; /* Offset: 0x040 (R/W) Receive FIFO Underflow Interrupt Clear Register */
uint8_t RESERVED7[3];
__IM uint8_t MSTICR; /* Offset: 0x044 (R/W) Multi-Master Interrupt Clear Register */
uint8_t RESERVED8[3];
__IM uint8_t ICR; /* Offset: 0x048 (R/W) Interrupt Clear Register */
uint8_t RESERVED9[3];
__IOM uint8_t DMACR; /* Offset: 0x04C (R/W) DMA Control Register */
uint8_t RESERVED10[3];
__IOM uint8_t DMATDLR; /* Offset: 0x050 (R/W) DMA Transmoit Data Level */
uint8_t RESERVED11[3];
__IOM uint8_t DMARDLR; /* Offset: 0x054 (R/W) DMA Receive Data Level */
uint8_t RESERVED12[3];
__IM uint32_t IDR; /* Offset: 0x058 (R/W) identification register */
uint32_t RESERVED13;
__IOM uint16_t DR; /* Offset: 0x060 (R/W) Data Register */
uint16_t RESERVED14[17];
__IOM uint8_t WR; /* Offset: 0x0A0 (R/W) SPI is Master or Slave Select Register */
} dw_spi_reg_t;
#endif /* __DW_SPI_H */

View file

@ -0,0 +1,49 @@
/*
* Copyright (C) 2017 C-SKY Microsystems Co., Ltd. All rights reserved.
*
* 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 dw_timer.h
* @brief header file for timer driver
* @version V1.0
* @date 02. June 2017
******************************************************************************/
#ifndef __DW_TIMER_H
#define __DW_TIMER_H
#include <stdio.h>
#include "soc.h"
/*
* define the bits for TxControl
*/
#define DW_TIMER_TXCONTROL_ENABLE (1UL << 0)
#define DW_TIMER_TXCONTROL_MODE (1UL << 1)
#define DW_TIMER_TXCONTROL_INTMASK (1UL << 2)
#define DW_TIMER_INIT_DEFAULT_VALUE (0xffffffff / SYSTEM_CLOCK * 1000000)
typedef struct {
__IOM uint32_t TxLoadCount; /* Offset: 0x000 (R/W) Receive buffer register */
__IM uint32_t TxCurrentValue; /* Offset: 0x004 (R) Transmission hold register */
__IOM uint8_t TxControl: 4; /* Offset: 0x008 (R/W) Clock frequency division low section register */
uint8_t RESERVED0[3];
__IM uint8_t TxEOI: 1; /* Offset: 0x00c (R) Clock frequency division high section register */
uint8_t RESERVED1[3];
__IM uint8_t TxIntStatus: 1; /* Offset: 0x010 (R) Interrupt enable register */
uint8_t RESERVED2[3];
} dw_timer_reg_t;
#endif /* __DW_TIMER_H */

View file

@ -0,0 +1,116 @@
/*
* Copyright (C) 2017 C-SKY Microsystems Co., Ltd. All rights reserved.
*
* 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 dw_usart.h
* @brief header file for usart driver
* @version V1.0
* @date 02. June 2017
******************************************************************************/
#ifndef __DW_USART_H
#define __DW_USART_H
#include <stdio.h>
#include "errno.h"
#include "soc.h"
#define BAUDRATE_DEFAULT 19200
#define UART_BUSY_TIMEOUT 1000000
#define UART_RECEIVE_TIMEOUT 1000
#define UART_TRANSMIT_TIMEOUT 1000
#define UART_MAX_FIFO 0x10
/* UART register bit definitions */
#define USR_UART_BUSY 0x01
#define USR_UART_TFE 0x04
#define USR_UART_RFNE 0x08
#define LSR_DATA_READY 0x01
#define LSR_THR_EMPTY 0x20
#define IER_RDA_INT_ENABLE 0x01
#define IER_THRE_INT_ENABLE 0x02
#define IIR_NO_ISQ_PEND 0x01
#define IIR_RECV_LINE_ENABLE 0x04
#define LCR_SET_DLAB 0x80 /* enable r/w DLR to set the baud rate */
#define LCR_PARITY_ENABLE 0x08 /* parity enabled */
#define LCR_PARITY_EVEN 0x10 /* Even parity enabled */
#define LCR_PARITY_ODD 0xef /* Odd parity enabled */
#define LCR_WORD_SIZE_5 0xfc /* the data length is 5 bits */
#define LCR_WORD_SIZE_6 0x01 /* the data length is 6 bits */
#define LCR_WORD_SIZE_7 0x02 /* the data length is 7 bits */
#define LCR_WORD_SIZE_8 0x03 /* the data length is 8 bits */
#define LCR_STOP_BIT1 0xfb /* 1 stop bit */
#define LCR_STOP_BIT2 0x04 /* 1.5 stop bit */
#define DW_LSR_PFE 0x80
#define DW_LSR_TEMT 0x40
#define DW_LSR_THRE 0x40
#define DW_LSR_BI 0x10
#define DW_LSR_FE 0x08
#define DW_LSR_PE 0x04
#define DW_LSR_OE 0x02
#define DW_LSR_DR 0x01
#define DW_LSR_TRANS_EMPTY 0x20
#define DW_FCR_FIFOE 0x01
#define DW_FCR_RFIFOR 0x02
#define DW_FCR_XFIFOR 0x04
#define DW_FCR_RT_FIFO_SINGLE 0x0 << 6 /* rcvr trigger 1 character in the FIFO */
#define DW_FCR_RT_FIFO_QUARTER 0x1 << 6 /* rcvr trigger FIFO 1/4 full */
#define DW_FCR_RT_FIFO_HALF 0x2 << 6 /* rcvr trigger FIFO 1/2 full */
#define DW_FCR_RT_FIFO_LESSTWO 0x3 << 6 /* rcvr trigger FIFO 2 less than full */
#define DW_FCR_TET_FIFO_EMPTY 0x0 << 4 /* tx empty trigger FIFO empty */
#define DW_FCR_TET_FIFO_TWO 0x1 << 4 /* tx empty trigger 2 characters in the FIFO */
#define DW_FCR_TET_FIFO_QUARTER 0x2 << 4 /* tx empty trigger FIFO 1/4 full */
#define DW_FCR_TET_FIFO_HALF 0x3 << 4 /* tx empty trigger FIFO 1/2 full*/
#define DW_IIR_THR_EMPTY 0x02 /* threshold empty */
#define DW_IIR_RECV_DATA 0x04 /* received data available */
#define DW_IIR_RECV_LINE 0x06 /* receiver line status */
#define DW_IIR_CHAR_TIMEOUT 0x0c /* character timeout */
#define DW_MCR_AFCE 0x20 /* Auto Flow Control Enable */
#define DW_MCR_RTS 0x02
typedef struct {
union {
__IM uint32_t RBR; /* Offset: 0x000 (R/ ) Receive buffer register */
__OM uint32_t THR; /* Offset: 0x000 ( /W) Transmission hold register */
__IOM uint32_t DLL; /* Offset: 0x000 (R/W) Clock frequency division low section register */
};
union {
__IOM uint32_t DLH; /* Offset: 0x004 (R/W) Clock frequency division high section register */
__IOM uint32_t IER; /* Offset: 0x004 (R/W) Interrupt enable register */
};
union {
__IM uint32_t IIR; /* Offset: 0x008 (R/ ) Interrupt indicia register */
__OM uint32_t FCR; /* Offset: 0x008 ( /W) FIFO control register */
};
__IOM uint32_t LCR; /* Offset: 0x00C (R/W) Transmission control register */
__IOM uint32_t MCR; /* Offset: 0x010 (R/W) Modem control register */
__IM uint32_t LSR; /* Offset: 0x014 (R/ ) Transmission state register */
__IM uint32_t MSR; /* Offset: 0x018 (R/ ) Modem state register */
uint32_t RESERVED1[21];
__IOM uint32_t FAR; /* Offset: 0x070 (R/W) FIFO accesss register */
__IM uint32_t TFR; /* Offset: 0x074 (R/ ) transmit FIFO read */
__OM uint32_t RFW; /* Offset: 0x078 ( /W) receive FIFO write */
__IM uint32_t USR; /* Offset: 0x07c (R/ ) UART state register */
__IM uint32_t TFL; /* Offset: 0x080 (R/ ) transmit FIFO level */
__IM uint32_t RFL; /* Offset: 0x084 (R/ ) receive FIFO level */
} dw_usart_reg_t;
#endif /* __DW_USART_H */

View file

@ -0,0 +1,44 @@
/*
* Copyright (C) 2017 C-SKY Microsystems Co., Ltd. All rights reserved.
*
* 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 dw_wdt.h
* @brief header file for wdt driver
* @version V1.0
* @date 02. June 2017
******************************************************************************/
#ifndef __DW_WDT_H
#define __DW_WDT_H
#include <stdio.h>
#include "soc.h"
#define DW_WDT_CRR_RESET 0x76
typedef struct {
__IOM uint8_t WDT_CR:5; /* Offset: 0x000 (R/W) WDT control register */
uint8_t RESERVED0[3];
__IOM uint8_t WDT_TORR; /* Offset: 0x004 (R/W) WDT timeout range register */
uint8_t RESERVED1[3];
__IM uint32_t WDT_CCVR; /* Offset: 0x008 (R/ ) WDT current counter value register */
__OM uint8_t WDT_CRR:8; /* Offset: 0x00C ( /W) WDT count restart register */
uint8_t RESERVED2[3];
__IM uint8_t WDT_STAT:1; /* Offset: 0x010 (R/ ) WDT interrupt status register */
uint8_t RESERVED3[3];
__IM uint8_t WDT_EOI:1; /* Offset: 0x014 (R/ ) WDT interrupt clear register */
uint8_t RESERVED4[3];
} dw_wdt_reg_t;
#endif /* __DW_WDT_H */

View file

@ -0,0 +1,314 @@
/*
* Copyright (C) 2017 C-SKY Microsystems Co., Ltd. All rights reserved.
*
* 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 ck_pwm.c
* @brief CSI Source File for PWM Driver
* @version V1.0
* @date 02. June 2017
******************************************************************************/
#include <csi_config.h>
#include "ck_pwm.h"
#include "drv_pwm.h"
#include "soc.h"
#define ERR_PWM(errno) (CSI_DRV_ERRNO_PWM_BASE | errno)
#define PWM_NULL_PARAM_CHK(para) \
do { \
if (para == NULL) { \
return ERR_PWM(DRV_ERROR_PARAMETER); \
} \
} while (0)
typedef struct {
uint32_t base;
uint32_t irq;
uint32_t ch_num;
} ck_pwm_priv_t;
extern int32_t target_pwm_init(int32_t pwm_pin, uint32_t *ch_num, uint32_t *base, uint32_t *irq);
static ck_pwm_priv_t pwm_instance[CONFIG_PWM_NUM];
/**
\brief Initialize PWM Interface. 1. Initializes the resources needed for the PWM interface 2.registers event callback function
\param[in] pwm pin of gpio
\return handle pwm handle to operate.
*/
pwm_handle_t drv_pwm_initialize(int32_t pwm_pin)
{
uint32_t base = 0u;
uint32_t irq = 0u;
uint32_t ch_num = 0u;
int32_t idx = target_pwm_init(pwm_pin, &ch_num, &base, &irq);
if (idx < 0 || idx >= CONFIG_PWM_NUM) {
return NULL;
}
ck_pwm_priv_t *pwm_priv = &pwm_instance[idx];
pwm_priv->base = base;
pwm_priv->irq = irq;
pwm_priv->ch_num = ch_num;
return pwm_priv;
}
/**
\brief De-initialize PWM Interface. stops operation and releases the software resources used by the interface
\param[in] handle pwm handle to operate.
\return \ref execution_status
*/
int32_t drv_pwm_uninitialize(pwm_handle_t handle)
{
PWM_NULL_PARAM_CHK(handle);
return 0;
}
/**
\brief config pwm mode.
\param[in] handle pwm handle to operate.
\param[in] sysclk configured system clock.
\param[in] period_us the PWM period in us
\param[in] duty the PMW duty. ( 0 - 10000 represents 0% - 100% ,other values are invalid)
\return \ref execution_status
*/
int32_t drv_pwm_config(pwm_handle_t handle, uint32_t sysclk, uint32_t period_us, uint32_t duty)
{
if (handle == NULL || duty > 10000) {
return ERR_PWM(DRV_ERROR_PARAMETER);
}
ck_pwm_priv_t *pwm_priv = handle;
uint32_t chn = pwm_priv->ch_num;
uint32_t counter = (sysclk / 1000000 * period_us);
if (counter >= 0xffffffff) {
return ERR_PWM(DRV_ERROR_PARAMETER);
}
uint32_t data_width;
data_width = (uint32_t)((counter * duty / 10000));
ck_pwm_reg_t *addr = (ck_pwm_reg_t *)(pwm_priv->base);
uint32_t ctl_tmp = addr->PWMCTL;
uint32_t temp;
if (chn == CKENUM_PWM_CH0 || chn == CKENUM_PWM_CH1) {
ctl_tmp &= 0xfffffffe;
addr->PWMCTL = ctl_tmp | (uint32_t)CKENUM_PWM_COUNT_UP;
temp = addr->PWM01LOAD;
temp &= 0xffff0000;
addr->PWM01LOAD = temp | counter;
temp = addr->PWM0CMP;
if (chn == CKENUM_PWM_CH0) {
temp &= 0xffff0000;
addr->PWM0CMP = temp | data_width;
} else {
temp &= 0x0000ffff;
addr->PWM0CMP = temp | data_width << 16;
}
}
if (chn == CKENUM_PWM_CH2 || chn == CKENUM_PWM_CH3) {
ctl_tmp &= 0xfffffffd;
addr->PWMCTL = ctl_tmp | (uint32_t)CKENUM_PWM_COUNT_UP << 1;
temp = addr->PWM01LOAD;
temp &= 0x0000ffff;
addr->PWM01LOAD = temp | counter << 16 ;
temp = addr->PWM1CMP;
if (chn == CKENUM_PWM_CH2) {
temp &= 0xffff0000;
addr->PWM1CMP = temp | data_width;
} else {
temp &= 0x0000ffff;
addr->PWM1CMP = temp | data_width << 16;
}
}
if (chn == CKENUM_PWM_CH4 || chn == CKENUM_PWM_CH5) {
ctl_tmp &= 0xfffffffb;
addr->PWMCTL = ctl_tmp | (uint32_t)CKENUM_PWM_COUNT_UP << 2;
temp = addr->PWM23LOAD;
temp &= 0xffff0000;
addr->PWM23LOAD = temp | counter;
temp = addr->PWM2CMP;
if (chn == CKENUM_PWM_CH4) {
temp &= 0xffff0000;
addr->PWM2CMP = temp | data_width;
} else {
temp &= 0x0000ffff;
addr->PWM2CMP = temp | data_width << 16;
}
}
if (chn == CKENUM_PWM_CH6 || chn == CKENUM_PWM_CH7) {
ctl_tmp &= 0xfffffff7;
addr->PWMCTL = ctl_tmp | (uint32_t)CKENUM_PWM_COUNT_UP << 3;
temp = addr->PWM23LOAD;
temp &= 0x0000ffff;
addr->PWM23LOAD = temp | counter << 16 ;
temp = addr->PWM3CMP;
if (chn == CKENUM_PWM_CH6) {
temp &= 0xffff0000;
addr->PWM3CMP = temp | data_width;
} else {
temp &= 0x0000ffff;
addr->PWM3CMP = temp | data_width << 16;
}
}
if (chn == CKENUM_PWM_CH8 || chn == CKENUM_PWM_CH9) {
ctl_tmp &= 0xffffffef;
addr->PWMCTL = ctl_tmp | (uint32_t)CKENUM_PWM_COUNT_UP << 4;
temp = addr->PWM45LOAD;
temp &= 0xffff0000;
addr->PWM45LOAD = temp | counter ;
temp = addr->PWM4CMP;
if (chn == CKENUM_PWM_CH8) {
temp &= 0xffff0000;
addr->PWM4CMP = temp | data_width;
} else {
temp &= 0x0000ffff;
addr->PWM4CMP = temp | data_width << 16;
}
}
if (chn == CKENUM_PWM_CH10 || chn == CKENUM_PWM_CH11) {
ctl_tmp &= 0xffffffdf;
addr->PWMCTL = ctl_tmp | (uint32_t)CKENUM_PWM_COUNT_UP << 5;
temp = addr->PWM45LOAD;
temp &= 0x0000ffff;
addr->PWM45LOAD = temp | counter << 16 ;
temp = addr->PWM5CMP;
if (chn == CKENUM_PWM_CH10) {
temp &= 0xffff0000;
addr->PWM5CMP = temp | data_width;
} else {
temp &= 0x0000ffff;
addr->PWM5CMP = temp | data_width << 16;
}
}
return 0;
}
/**
\brief start generate pwm signal.
\param[in] handle pwm handle to operate.
\param[in] pwm channel number.
\return \ref execution_status
*/
int32_t drv_pwm_start(pwm_handle_t handle)
{
PWM_NULL_PARAM_CHK(handle);
ck_pwm_priv_t *pwm_priv = handle;
ck_pwm_reg_t *addr = (ck_pwm_reg_t *)(pwm_priv->base);
uint32_t chn = pwm_priv->ch_num;
if (chn == CKENUM_PWM_CH0 || chn == CKENUM_PWM_CH1) {
addr->PWMCFG |= 0x00000003; /* PWM0 output enable */
}
if (chn == CKENUM_PWM_CH2 || chn == CKENUM_PWM_CH3) {
addr->PWMCFG |= 0x0000000C; /* PWM1 output enable */
}
if (chn == CKENUM_PWM_CH4 || chn == CKENUM_PWM_CH5) {
addr->PWMCFG |= 0x00000030; /* PWM2 output enable */
}
if (chn == CKENUM_PWM_CH6 || chn == CKENUM_PWM_CH7) {
addr->PWMCFG |= 0x000000C0; /* PWM3 output enable */
}
if (chn == CKENUM_PWM_CH8 || chn == CKENUM_PWM_CH9) {
addr->PWMCFG |= 0x00000300; /* PWM4 output enable */
}
if (chn == CKENUM_PWM_CH10 || chn == CKENUM_PWM_CH11) {
addr->PWMCFG |= 0x00000C00; /* PWM5 output enable */
}
return 0;
}
/**
\brief Stop generate pwm signal.
\param[in] handle pwm handle to operate.
\return \ref execution_status
*/
int32_t drv_pwm_stop(pwm_handle_t handle)
{
PWM_NULL_PARAM_CHK(handle);
ck_pwm_priv_t *pwm_priv = handle;
ck_pwm_reg_t *addr = (ck_pwm_reg_t *)(pwm_priv->base);
uint32_t chn = pwm_priv->ch_num;
if (chn == CKENUM_PWM_CH0 || chn == CKENUM_PWM_CH1) {
addr->PWMCFG &= ~0x00000003; /* PWM0 output disable */
}
if (chn == CKENUM_PWM_CH2 || chn == CKENUM_PWM_CH3) {
addr->PWMCFG &= ~0x0000000C; /* PWM1 output disable */
}
if (chn == CKENUM_PWM_CH4 || chn == CKENUM_PWM_CH5) {
addr->PWMCFG &= ~0x00000030; /* PWM2 output disable */
}
if (chn == CKENUM_PWM_CH6 || chn == CKENUM_PWM_CH7) {
addr->PWMCFG &= ~0x000000C0; /* PWM3 output disable */
}
if (chn == CKENUM_PWM_CH8 || chn == CKENUM_PWM_CH9) {
addr->PWMCFG &= ~0x00000300; /* PWM4 output disable */
}
if (chn == CKENUM_PWM_CH10 || chn == CKENUM_PWM_CH11) {
addr->PWMCFG &= ~0x00000C00; /* PWM5 output disable */
}
return 0;
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,664 @@
/*
* Copyright (C) 2017 C-SKY Microsystems Co., Ltd. All rights reserved.
*
* 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 ck_rtc.c
* @brief CSI Source File for RTC Driver
* @version V1.0
* @date 02. June 2017
******************************************************************************/
#include <csi_config.h>
#include <stdbool.h>
#include <string.h>
#include "ck_rtc.h"
#include "csi_core.h"
#include "drv_rtc.h"
#include "soc.h"
#define ERR_RTC(errno) (CSI_DRV_ERRNO_RTC_BASE | errno)
#define RTC_NULL_PARAM_CHK(para) \
do { \
if (para == NULL) { \
return ERR_RTC(DRV_ERROR_PARAMETER); \
} \
} while (0)
typedef struct {
uint32_t base;
uint32_t irq;
rtc_event_cb_t cb_event;
struct tm rtc_base;
} ck_rtc_priv_t;
extern void mdelay(uint32_t ms);
extern int32_t target_get_rtc_count(void);
extern int32_t target_get_rtc(int32_t idx, uint32_t *base, uint32_t *irq);
static ck_rtc_priv_t rtc_instance[CONFIG_RTC_NUM];
static uint8_t leap_year[12] = {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
static uint8_t noleap_year[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
static const uint16_t g_noleap_daysbeforemonth[13] = {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365};
//static const uint16_t g_leap_daysbeforemonth[13] = {0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366};
static const rtc_capabilities_t rtc_capabilities = {
.interrupt_mode = 1, /* supports Interrupt mode */
.wrap_mode = 0 /* supports wrap mode */
};
static inline int clock_isleapyear(int year)
{
return (year % 400) ? ((year % 100) ? ((year % 4) ? 0 : 1) : 0) : 1;
}
static inline int32_t ck_rtc_enable(ck_rtc_reg_t *addr)
{
uint32_t value;
value = addr->RTC_CCR;
value |= 1 << 2;
addr->RTC_CCR = value;
return 0;
}
static inline int32_t ck_rtc_disable(ck_rtc_reg_t *addr)
{
uint32_t value;
value = addr->RTC_CCR;
value &= ~(1 << 2);
addr->RTC_CCR = value;
return 0;
}
static int ck_rtc_settime(ck_rtc_reg_t *addr, uint32_t settime)
{
uint64_t time = settime;
if (settime < 0) {
return ERR_RTC(DRV_ERROR_PARAMETER);
}
time = time * SYSTEM_CLOCK / 16384;
time = time / 1000;
addr->RTC_CLR = (uint32_t)time;
/* after setting RTC counter load register(RTC_CLT), loading to RTC_CCVR need two rtc clocks.
* two rtc clocks about 3ms. setting 10ms to ensure operation is completed.
*/
mdelay(10);
return 0;
}
static uint64_t ck_rtc_readtime(ck_rtc_reg_t *addr)
{
uint64_t time;
time = addr->RTC_CCVR;
#ifdef CONFIG_CHIP_HOBBIT1_2
time = time * 32768 * 1000 / 3000 ;
#else
time = time * 16384 / ( SYSTEM_CLOCK / 1000 );
#endif
return time;
}
static int ck_check_tm_ok(struct tm *rtctime)
{
if (rtctime->tm_year < 70 || rtctime->tm_year >= 200) {
goto error_time;
}
int32_t leap = 1;
leap = clock_isleapyear(rtctime->tm_year + 1900);
if (rtctime->tm_sec < 0 || rtctime->tm_sec >= 60) {
goto error_time;
}
if (rtctime->tm_min < 0 || rtctime->tm_min >= 60) {
goto error_time;
}
if (rtctime->tm_hour < 0 || rtctime->tm_hour >= 24) {
goto error_time;
}
if (rtctime->tm_mon < 0 || rtctime->tm_mon >= 12) {
goto error_time;
}
if (leap) {
if (rtctime->tm_mday < 1 || rtctime->tm_mday > leap_year[rtctime->tm_mon]) {
goto error_time;
}
} else {
if (rtctime->tm_mday < 1 || rtctime->tm_mday > noleap_year[rtctime->tm_mon]) {
goto error_time;
}
}
return 0;
error_time:
return ERR_RTC(RTC_ERROR_TIME);
}
static int clock_daysbeforemonth(int month, bool leapyear)
{
int retval = g_noleap_daysbeforemonth[month];
if (month >= 2 && leapyear) {
retval++;
}
return retval;
}
static time_t clock_calendar2utc(int year, int month, int day)
{
time_t days;
/* Years since epoch in units of days (ignoring leap years). */
days = (year - 1970) * 365;
/* Add in the extra days for the leap years prior to the current year. */
days += (year - 1969) >> 2;
/* Add in the days up to the beginning of this month. */
days += (time_t)clock_daysbeforemonth(month, clock_isleapyear(year));
/* Add in the days since the beginning of this month (days are 1-based). */
days += day - 1;
/* Then convert the seconds and add in hours, minutes, and seconds */
return days;
}
time_t mktime(struct tm *tp)
{
time_t ret;
time_t jdn;
/* Get the EPOCH-relative julian date from the calendar year,
* month, and date
*/
ret = ck_check_tm_ok(tp);
if (ret < 0) {
return -1;
}
jdn = clock_calendar2utc(tp->tm_year + 1900, tp->tm_mon, tp->tm_mday);
/* Return the seconds into the julian day. */
ret = ((jdn * 24 + tp->tm_hour) * 60 + tp->tm_min) * 60 + tp->tm_sec;
return ret;
}
static void clock_utc2calendar(time_t days, int *year, int *month,
int *day)
{
/* There is one leap year every four years, so we can get close with the
* following:
*/
int value = days / (4 * 365 + 1); /* Number of 4-years periods since the epoch */
days -= value * (4 * 365 + 1); /* Remaining days */
value <<= 2; /* Years since the epoch */
/* Then we will brute force the next 0-3 years */
bool leapyear;
int tmp;
for (; ;) {
/* Is this year a leap year (we'll need this later too) */
leapyear = clock_isleapyear(value + 1970);
/* Get the number of days in the year */
tmp = (leapyear ? 366 : 365);
/* Do we have that many days? */
if (days >= tmp) {
/* Yes.. bump up the year */
value++;
days -= tmp;
} else {
/* Nope... then go handle months */
break;
}
}
/* At this point, value has the year and days has number days into this year */
*year = 1970 + value;
/* Handle the month (zero based) */
int min = 0;
int max = 11;
do {
/* Get the midpoint */
value = (min + max) >> 1;
/* Get the number of days that occurred before the beginning of the month
* following the midpoint.
*/
tmp = clock_daysbeforemonth(value + 1, leapyear);
/* Does the number of days before this month that equal or exceed the
* number of days we have remaining?
*/
if (tmp > days) {
/* Yes.. then the month we want is somewhere from 'min' and to the
* midpoint, 'value'. Could it be the midpoint?
*/
tmp = clock_daysbeforemonth(value, leapyear);
if (tmp > days) {
/* No... The one we want is somewhere between min and value-1 */
max = value - 1;
} else {
/* Yes.. 'value' contains the month that we want */
break;
}
} else {
/* No... The one we want is somwhere between value+1 and max */
min = value + 1;
}
/* If we break out of the loop because min == max, then we want value
* to be equal to min == max.
*/
value = min;
} while (min < max);
/* The selected month number is in value. Subtract the number of days in the
* selected month
*/
days -= clock_daysbeforemonth(value, leapyear);
/* At this point, value has the month into this year (zero based) and days has
* number of days into this month (zero based)
*/
*month = value + 1; /* 1-based */
*day = days + 1; /* 1-based */
}
struct tm *gmtime_r(const time_t *timer, struct tm *result)
{
time_t epoch;
time_t jdn;
int year;
int month;
int day;
int hour;
int min;
int sec;
/* Get the seconds since the EPOCH */
epoch = *timer;
/* Convert to days, hours, minutes, and seconds since the EPOCH */
jdn = epoch / SEC_PER_DAY;
epoch -= SEC_PER_DAY * jdn;
hour = epoch / SEC_PER_HOUR;
epoch -= SEC_PER_HOUR * hour;
min = epoch / SEC_PER_MIN;
epoch -= SEC_PER_MIN * min;
sec = epoch;
/* Convert the days since the EPOCH to calendar day */
clock_utc2calendar(jdn, &year, &month, &day);
/* Then return the struct tm contents */
result->tm_year = (int)year - 1900; /* Relative to 1900 */
result->tm_mon = (int)month - 1; /* zero-based */
result->tm_mday = (int)day; /* one-based */
result->tm_hour = (int)hour;
result->tm_min = (int)min;
result->tm_sec = (int)sec;
return result;
}
static int ck_rtc_setmarchtime(ck_rtc_reg_t *addr, int64_t settime)
{
int64_t time = settime;
if (settime < 0 || time >= 0x8000000000000000) {
return ERR_RTC(DRV_ERROR_PARAMETER);
}
#ifdef CONFIG_CHIP_HOBBIT1_2
time = time * 6555 / 32768;
#else
time = time * 20000 / 16384;
#endif
time += addr->RTC_CCVR;
addr->RTC_CMR = (uint32_t)time;
return 0;
}
static int32_t ck_rtc_int_enable(ck_rtc_reg_t *addr)
{
int value = addr->RTC_CCR;
value |= 1 << 0;
addr->RTC_CCR = value;
return 0;
}
static int32_t ck_rtc_int_disable(ck_rtc_reg_t *addr)
{
uint32_t value = addr->RTC_CCR;
value &= ~(1 << 0);
addr->RTC_CCR = value;
ck_rtc_setmarchtime(addr, ck_rtc_readtime(addr));
return 0;
}
void ck_rtc_irqhandler(int32_t idx)
{
ck_rtc_priv_t *rtc_priv = &rtc_instance[idx];
ck_rtc_reg_t *addr = (ck_rtc_reg_t *)(rtc_priv->base);
addr->RTC_EOI;
if (rtc_priv->cb_event) {
rtc_priv->cb_event(idx, RTC_EVENT_TIMER_INTRERRUPT);
}
}
/**
\brief Initialize RTC Interface. 1. Initializes the resources needed for the RTC interface 2.registers event callback function
\param[in] idx rtc index
\param[in] cb_event Pointer to \ref rtc_event_cb_t
\return pointer to rtc instance
*/
rtc_handle_t csi_rtc_initialize(int32_t idx, rtc_event_cb_t cb_event)
{
if (idx < 0 || idx >= CONFIG_RTC_NUM) {
return NULL;
}
int32_t real_idx;
uint32_t base = 0u;
uint32_t irq;
real_idx = target_get_rtc(idx, &base, &irq);
if (real_idx != idx) {
return NULL;
}
ck_rtc_priv_t *rtc_priv;
rtc_priv = &rtc_instance[idx];
rtc_priv->base = base;
rtc_priv->irq = irq;
ck_rtc_reg_t *addr = (ck_rtc_reg_t *)(rtc_priv->base);
rtc_priv->cb_event = cb_event;
addr->RTC_CCR = 0;
addr->RTC_EOI;
csi_vic_clear_pending_irq(rtc_priv->irq);
csi_vic_enable_irq(rtc_priv->irq);
return (rtc_handle_t)rtc_priv;
}
/**
\brief De-initialize RTC Interface. stops operation and releases the software resources used by the interface
\param[in] handle rtc handle to operate.
\return \ref execution_status
*/
int32_t csi_rtc_uninitialize(rtc_handle_t handle)
{
RTC_NULL_PARAM_CHK(handle);
ck_rtc_priv_t *rtc_priv = handle;
rtc_priv->cb_event = NULL;
csi_vic_disable_irq(rtc_priv->irq);
return 0;
}
/**
\brief Get driver capabilities.
\param[in] idx rtc index
\return \ref rtc_capabilities_t
*/
rtc_capabilities_t csi_rtc_get_capabilities(int32_t idx)
{
if (idx < 0 || idx >= CONFIG_SPI_NUM) {
rtc_capabilities_t ret;
memset(&ret, 0, sizeof(rtc_capabilities_t));
return ret;
}
return rtc_capabilities;
}
/**
\brief Set RTC timer.
\param[in] handle rtc handle to operate.
\param[in] rtctime \ref struct tm
\return \ref execution_status
*/
int32_t csi_rtc_set_time(rtc_handle_t handle, const struct tm *rtctime)
{
RTC_NULL_PARAM_CHK(handle);
RTC_NULL_PARAM_CHK(rtctime);
ck_rtc_priv_t *rtc_priv = handle;
ck_rtc_reg_t *addr = (ck_rtc_reg_t *)(rtc_priv->base);
int32_t ret = ck_check_tm_ok((struct tm *)rtctime);
if (ret < 0) {
return ret;
}
rtc_priv->rtc_base.tm_sec = rtctime->tm_sec;
rtc_priv->rtc_base.tm_min = rtctime->tm_min;
rtc_priv->rtc_base.tm_hour = rtctime->tm_hour;
rtc_priv->rtc_base.tm_mday = rtctime->tm_mday;
rtc_priv->rtc_base.tm_mon = rtctime->tm_mon;
rtc_priv->rtc_base.tm_year = rtctime->tm_year;
ck_rtc_settime(addr, 0);
return 0;
}
/**
\brief Get RTC timer.
\param[in] handle rtc handle to operate.
\param[in] rtctime \ref struct tm
\return \ref execution_status
*/
int32_t csi_rtc_get_time(rtc_handle_t handle, struct tm *rtctime)
{
RTC_NULL_PARAM_CHK(handle);
ck_rtc_priv_t *rtc_priv = handle;
ck_rtc_reg_t *addr = (ck_rtc_reg_t *)(rtc_priv->base);
time_t time = ck_rtc_readtime(addr);
time = time / 1000;
time += mktime(&(rtc_priv->rtc_base));
gmtime_r(&time, rtctime);
return 0;
}
/**
\brief Start RTC timer.
\param[in] handle rtc handle to operate.
\return \ref execution_status
*/
int32_t csi_rtc_start(rtc_handle_t handle)
{
RTC_NULL_PARAM_CHK(handle);
ck_rtc_priv_t *rtc_priv = handle;
ck_rtc_reg_t *addr = (ck_rtc_reg_t *)(rtc_priv->base);
ck_rtc_enable(addr);
return 0;
}
/**
\brief Stop RTC timer.
\param[in] handle rtc handle to operate.
\return \ref execution_status
*/
int32_t csi_rtc_stop(rtc_handle_t handle)
{
RTC_NULL_PARAM_CHK(handle);
ck_rtc_priv_t *rtc_priv = handle;
ck_rtc_reg_t *addr = (ck_rtc_reg_t *)(rtc_priv->base);
ck_rtc_disable(addr);
return 0;
}
/**
\brief Get RTC status.
\param[in] handle rtc handle to operate.
\return RTC status \ref rtc_status_t
*/
rtc_status_t csi_rtc_get_status(rtc_handle_t handle)
{
rtc_status_t rtc_status = {0};
if (handle == NULL) {
return rtc_status;
}
ck_rtc_priv_t *rtc_priv = handle;
ck_rtc_reg_t *addr = (ck_rtc_reg_t *)(rtc_priv->base);
if (addr->RTC_RSTAT & 0x1) {
rtc_status.active = 1;
}
return rtc_status;
}
/**
\brief config RTC timer.
\param[in] handle rtc handle to operate.
\param[in] rtctime time to wake up
\return error code
*/
int32_t csi_rtc_set_alarm(rtc_handle_t handle, const struct tm *rtctime)
{
int32_t ret;
struct tm current_time;
int64_t settime = 0;
RTC_NULL_PARAM_CHK(handle);
ck_rtc_priv_t *rtc_priv = (ck_rtc_priv_t *)handle;
ck_rtc_reg_t *addr = (ck_rtc_reg_t *)(rtc_priv->base);
ret = ck_check_tm_ok((struct tm *)rtctime);
if (ret < 0) {
goto error_time;
}
ret = csi_rtc_get_time(handle, &current_time);
#ifdef CONFIG_CHIP_HOBBIT1_2
settime = (mktime((struct tm *)rtctime) - mktime(&current_time));
#else
settime = (mktime((struct tm *)rtctime) - mktime(&current_time)) * 1000;
#endif
if(settime < 0)
{
goto error_time;
}
ck_rtc_setmarchtime(addr, settime);
return 0;
error_time:
return ERR_RTC(RTC_ERROR_TIME);
}
/**
\brief disable or enable RTC timer.
\param[in] handle rtc handle to operate.
\param[in] flag 1 - enable rtc alarm 0 - disable rtc alarm
\return error code
*/
int32_t csi_rtc_enable_alarm(rtc_handle_t handle, uint8_t en)
{
RTC_NULL_PARAM_CHK(handle);
ck_rtc_priv_t *rtc_priv = handle;
ck_rtc_reg_t *addr = (ck_rtc_reg_t *)(rtc_priv->base);
if (en == 1) {
ck_rtc_int_enable(addr);
} else if (en == 0) {
ck_rtc_int_disable(addr);
} else {
return ERR_RTC(DRV_ERROR_PARAMETER);
}
return 0;
}

View file

@ -0,0 +1,180 @@
/*
* Copyright (C) 2017 C-SKY Microsystems Co., Ltd. All rights reserved.
*
* 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 ck_sasc_v1.c
* @brief CSI Source File
* @version V1.0
* @date 02. June 2017
******************************************************************************/
#include <csi_config.h>
#include <stdio.h>
#include "drv_sasc.h"
#include "ck_sasc_v1.h"
static uint8_t region[REGION_MAX_NUM] = {0x0};
static uint32_t s_sram_base;
static uint32_t sram_addr_offset;
//
// Functions
//
static int alloc_region(void)
{
uint8_t i;
for (i=0; i<REGION_MAX_NUM; i++) {
if (region[i] != REGION_USED) {
return i;
}
}
return -1;
}
static inline void eflash_region_security_config(uint8_t region_idx, uint8_t is_security)
{
uint32_t temp = *(volatile uint32_t *)(EFLASH_REG_BASE + EFLASH_CAR);
temp &= ~(1 << region_idx);
temp |= (is_security << region_idx);
*(volatile uint32_t *)(EFLASH_REG_BASE + EFLASH_CAR) = temp;
}
static inline void eflash_region_cd_config(uint8_t region_idx, sasc_cd_e ucd)
{
uint32_t temp = *(volatile uint32_t *)(EFLASH_REG_BASE + EFLASH_CFG0);
temp &= ~(3 << (16 + region_idx*2));
temp |= (ucd << (16 + region_idx*2));
*(volatile uint32_t *)(EFLASH_REG_BASE + EFLASH_CFG0) = temp;
}
static inline void eflash_region_ap_config(uint8_t region_idx, sasc_ap_e sap, sasc_ap_e uap)
{
uint32_t temp = *(volatile uint32_t *)(EFLASH_REG_BASE + EFLASH_CFG0);
temp &= ~(3 << (region_idx*2));
temp |= (uap << (region_idx*2));
*(volatile uint32_t *)(EFLASH_REG_BASE + EFLASH_CFG0) = temp;
temp = *(volatile uint32_t *)(EFLASH_REG_BASE + EFLASH_CFG1);
temp &= ~(3 << (region_idx*2));
temp |= (sap << (region_idx*2));
*(volatile uint32_t *)(EFLASH_REG_BASE + EFLASH_CFG1) = temp;
}
static inline int eflash_region_address_config(uint8_t region_idx, uint32_t addr, sasc_size_e size)
{
uint32_t region_addr = (addr-EFLASH_ADDR_START) / EFLASH_SECTOR_SIZE;
*(volatile uint32_t *)(EFLASH_REG_BASE + EFLASH_RG0 + region_idx * 4) = region_addr << 23 | size;
return 0;
}
static inline void sram_region_security_config(uint8_t region_idx, uint8_t is_security)
{
uint32_t temp = *(volatile uint32_t *)(s_sram_base + SRAM_CAR);
temp &= ~(1 << region_idx);
temp |= (is_security << region_idx);
*(volatile uint32_t *)(s_sram_base + SRAM_CAR) = temp;
}
static inline void sram_region_cd_config(uint8_t region_idx, sasc_cd_e ucd)
{
uint32_t temp = *(volatile uint32_t *)(s_sram_base + SRAM_CFG0);
temp &= ~(3 << (16 + region_idx*2));
temp |= (ucd << (16 + region_idx*2));
*(volatile uint32_t *)(s_sram_base + SRAM_CFG0) = temp;
}
static inline void sram_region_ap_config(uint8_t region_idx, sasc_ap_e sap, sasc_ap_e uap)
{
uint32_t temp = *(volatile uint32_t *)(s_sram_base + SRAM_CFG0);
temp &= ~(3 << (region_idx*2));
temp |= (uap << (region_idx*2));
*(volatile uint32_t *)(s_sram_base + SRAM_CFG0) = temp;
temp = *(volatile uint32_t *)(s_sram_base + SRAM_CFG1);
temp &= ~(3 << (region_idx*2));
temp |= (sap << (region_idx*2));
*(volatile uint32_t *)(s_sram_base + SRAM_CFG1) = temp;
}
static inline void eflash_region_active_config(uint8_t region_idx)
{
*(volatile uint32_t *)(EFLASH_REG_BASE + EFLASH_CR) |= (1 << region_idx);
}
static inline void sram_region_active_config(uint8_t region_idx)
{
*(volatile uint32_t *)(s_sram_base + SRAM_CR) |= (1 << region_idx);
}
static inline int sram_region_address_config(uint8_t region_idx, uint32_t addr, sasc_size_e size)
{
uint32_t region_addr = (addr-SRAM_ADDR_START) / 4;
*(volatile uint32_t *)(s_sram_base + SRAM_RG0 + region_idx * 4) = region_addr << sram_addr_offset | size;
return 0;
}
static int32_t eflash_region_config(uint32_t addr, sasc_size_e size, sasc_ap_e sap, sasc_ap_e uap, sasc_cd_e ucd, uint8_t is_security)
{
uint8_t region_idx = alloc_region();
eflash_region_security_config(region_idx, is_security);
eflash_region_address_config(region_idx, addr, size);
eflash_region_cd_config(region_idx, ucd);
eflash_region_ap_config(region_idx, sap, uap);
eflash_region_active_config(region_idx);
return 0;
}
static int32_t sram_region_config(uint32_t addr, sasc_size_e size, sasc_ap_e sap, sasc_ap_e uap, sasc_cd_e ucd, uint8_t is_security)
{
uint8_t region_idx = alloc_region();
s_sram_base = SRAM_REG_BASE;
sram_addr_offset = 17;
sram_region_security_config(region_idx, is_security);
sram_region_address_config(region_idx, addr, size);
sram_region_cd_config(region_idx, ucd);
sram_region_ap_config(region_idx, sap, uap);
sram_region_active_config(region_idx);
return 0;
}
/**
\brief Config the sasc region attribute.
\param[in] handle sasc handle to operate.
\param[in] addr config region base address.
\param[in] size config region addr.
\param[in] sap super mode ap.
\param[in] uap user mode ap.
\param[in] scd super mode cd.
\param[in] ucd user mode cd.
\param[in] is_security config the region is security or not.
\return error code
*/
int32_t csi_sasc_config_region(uint32_t addr, sasc_size_e size, sasc_ap_e sap, sasc_ap_e uap, sasc_cd_e ucd, uint8_t is_security)
{
uint32_t ret;
if (IS_EFLASH_ADDR(addr)) {
ret = eflash_region_config(addr, size-SASC_EFLASH_1S, sap, uap, ucd, is_security);
} else if (IS_SRAM_ADDR(addr)) {
ret = sram_region_config(addr, size, sap, uap, ucd, is_security);
} else {
return -1;
}
return ret;
}

View file

@ -0,0 +1,188 @@
/*
* Copyright (C) 2017 C-SKY Microsystems Co., Ltd. All rights reserved.
*
* 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 ck_sasc_v2.c
* @brief CSI Source File
* @version V1.0
* @date 02. June 2017
******************************************************************************/
#include <csi_config.h>
#include <stdio.h>
#include "drv_sasc.h"
#include "ck_sasc_v2.h"
static uint8_t region[REGION_MAX_NUM] = {0x0};
static uint32_t s_sram_base;
static uint32_t sram_addr_offset;
//
// Functions
//
static int alloc_region(void)
{
uint8_t i;
for (i=0; i<REGION_MAX_NUM; i++) {
if (region[i] != REGION_USED) {
return i;
}
}
return -1;
}
static inline void eflash_region_security_config(uint8_t region_idx, uint8_t is_security)
{
uint32_t temp = *(volatile uint32_t *)(EFLASH_REG_BASE + EFLASH_CAR);
temp &= ~(1 << region_idx);
temp |= (is_security << region_idx);
*(volatile uint32_t *)(EFLASH_REG_BASE + EFLASH_CAR) = temp;
}
static inline void eflash_region_cd_config(uint8_t region_idx, sasc_cd_e ucd)
{
uint32_t temp = *(volatile uint32_t *)(EFLASH_REG_BASE + EFLASH_CFG0);
temp &= ~(3 << (16 + region_idx*2));
temp |= (ucd << (16 + region_idx*2));
*(volatile uint32_t *)(EFLASH_REG_BASE + EFLASH_CFG0) = temp;
}
static inline void eflash_region_ap_config(uint8_t region_idx, sasc_ap_e sap, sasc_ap_e uap)
{
uint32_t temp = *(volatile uint32_t *)(EFLASH_REG_BASE + EFLASH_CFG0);
temp &= ~(3 << (region_idx*2));
temp |= (uap << (region_idx*2));
*(volatile uint32_t *)(EFLASH_REG_BASE + EFLASH_CFG0) = temp;
temp = *(volatile uint32_t *)(EFLASH_REG_BASE + EFLASH_CFG1);
temp &= ~(3 << (region_idx*2));
temp |= (sap << (region_idx*2));
*(volatile uint32_t *)(EFLASH_REG_BASE + EFLASH_CFG1) = temp;
}
static inline int eflash_region_address_config(uint8_t region_idx, uint32_t addr, sasc_size_e size)
{
uint32_t region_addr = (addr-EFLASH_ADDR_START) / EFLASH_SECTOR_SIZE;
*(volatile uint32_t *)(EFLASH_REG_BASE + EFLASH_RG0 + region_idx * 4) = region_addr << 23 | size;
return 0;
}
static inline void sram_region_security_config(uint8_t region_idx, uint8_t is_security)
{
uint32_t temp = *(volatile uint32_t *)(s_sram_base + SRAM_CAR);
temp &= ~(1 << region_idx);
temp |= (is_security << region_idx);
*(volatile uint32_t *)(s_sram_base + SRAM_CAR) = temp;
}
static inline void sram_region_cd_config(uint8_t region_idx, sasc_cd_e ucd)
{
uint32_t temp = *(volatile uint32_t *)(s_sram_base + SRAM_CFG0);
temp &= ~(3 << (16 + region_idx*2));
temp |= (ucd << (16 + region_idx*2));
*(volatile uint32_t *)(s_sram_base + SRAM_CFG0) = temp;
}
static inline void sram_region_ap_config(uint8_t region_idx, sasc_ap_e sap, sasc_ap_e uap)
{
uint32_t temp = *(volatile uint32_t *)(s_sram_base + SRAM_CFG0);
temp &= ~(3 << (region_idx*2));
temp |= (uap << (region_idx*2));
*(volatile uint32_t *)(s_sram_base + SRAM_CFG0) = temp;
temp = *(volatile uint32_t *)(s_sram_base + SRAM_CFG1);
temp &= ~(3 << (region_idx*2));
temp |= (sap << (region_idx*2));
*(volatile uint32_t *)(s_sram_base + SRAM_CFG1) = temp;
}
static inline void eflash_region_active_config(uint8_t region_idx)
{
*(volatile uint32_t *)(EFLASH_REG_BASE + EFLASH_CR) |= (1 << region_idx);
}
static inline void sram_region_active_config(uint8_t region_idx)
{
*(volatile uint32_t *)(s_sram_base + SRAM_CR) |= (1 << region_idx);
}
static inline int sram_region_address_config(uint8_t region_idx, uint32_t addr, sasc_size_e size)
{
uint32_t region_addr = (addr-SRAM_ADDR_START) / 4;
*(volatile uint32_t *)(s_sram_base + SRAM_RG0 + region_idx * 4) = region_addr << sram_addr_offset | size;
return 0;
}
static int32_t eflash_region_config(uint32_t addr, sasc_size_e size, sasc_ap_e sap, sasc_ap_e uap, sasc_cd_e ucd, uint8_t is_security)
{
uint8_t region_idx = alloc_region();
eflash_region_security_config(region_idx, is_security);
eflash_region_address_config(region_idx, addr, size);
eflash_region_cd_config(region_idx, ucd);
eflash_region_ap_config(region_idx, sap, uap);
eflash_region_active_config(region_idx);
return 0;
}
static int32_t sram_region_config(uint32_t addr, sasc_size_e size, sasc_ap_e sap, sasc_ap_e uap, sasc_cd_e ucd, uint8_t is_security)
{
uint8_t region_idx = alloc_region();
if (IS_SRAM0_ADDR(addr)) {
s_sram_base = SRAM0_ADDR_START;
sram_addr_offset = 20;
} else if (IS_SRAM1_ADDR(addr)) {
s_sram_base = SRAM1_ADDR_START;
sram_addr_offset = 20;
} else if (IS_SRAM2_ADDR(addr)) {
s_sram_base = SRAM2_ADDR_START;
sram_addr_offset = 19;
}
sram_region_security_config(region_idx, is_security);
sram_region_address_config(region_idx, addr, size);
sram_region_cd_config(region_idx, ucd);
sram_region_ap_config(region_idx, sap, uap);
sram_region_active_config(region_idx);
return 0;
}
/**
\brief Config the sasc region attribute.
\param[in] handle sasc handle to operate.
\param[in] addr config region base address.
\param[in] size config region addr.
\param[in] sap super mode ap.
\param[in] uap user mode ap.
\param[in] scd super mode cd.
\param[in] ucd user mode cd.
\param[in] is_security config the region is security or not.
\return error code
*/
int32_t csi_sasc_config_region(uint32_t addr, sasc_size_e size, sasc_ap_e sap, sasc_ap_e uap, sasc_cd_e ucd, uint8_t is_security)
{
uint32_t ret;
if (IS_EFLASH_ADDR(addr)) {
ret = eflash_region_config(addr, size-SASC_EFLASH_1S, sap, uap, ucd, is_security);
} else if (IS_SRAM_ADDR(addr)) {
ret = sram_region_config(addr, size, sap, uap, ucd, is_security);
} else {
return -1;
}
return ret;
}

View file

@ -0,0 +1,576 @@
/*
* Copyright (C) 2017 C-SKY Microsystems Co., Ltd. All rights reserved.
*
* 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 ck_sha_v1.c
* @brief CSI Source File for SHA Driver
* @version V1.0
* @date 02. June 2017
******************************************************************************/
#include <csi_config.h>
#include <stdio.h>
#include <string.h>
#include <stdbool.h>
#include "drv_sha.h"
#include "ck_sha_v1.h"
#include "csi_core.h"
#ifndef CONFIG_SHA_SUPPORT_MUL_THREAD
#define CONFIG_SHA_SUPPORT_MUL_THREAD 1
#endif
typedef struct {
uint32_t base;
uint32_t irq;
sha_event_cb_t cb;
sha_status_t status;
sha_mode_e mode;
sha_endian_mode_e endian;
#ifdef CONFIG_SHA_SUPPORT_MUL_THREAD
uint32_t state[16];
uint32_t sha_buffer[32];
uint32_t total;
uint8_t first_cal;
#endif
} ck_sha_priv_t;
extern int32_t target_get_sha_count(void);
extern int32_t target_get_sha(int32_t idx, uint32_t *base, uint32_t *irq);
extern void mdelay(uint32_t ms);
#ifndef CONFIG_SHA_SUPPORT_MUL_THREAD
static ck_sha_priv_t sha_handle[CONFIG_SHA_NUM];
#endif
bool finish_flag = 0;
/* Driver Capabilities */
static const sha_capabilities_t driver_capabilities = {
.sha1 = 1, /* sha1 mode */
.sha224 = 1, /* sha224 mode */
.sha256 = 1, /* sha256 mode */
.sha384 = 1, /* sha384 mode */
.sha512 = 1, /* sha512 mode */
.sha512_224 = 0, /* sha512_224 mode */
.sha512_256 = 0, /* sha512_256 mode */
.endianmode = 0, /* endian mode */
.interruptmode = 0 /* interrupt mode */
};
#define ERR_SHA(errno) (CSI_DRV_ERRNO_SHA_BASE | errno)
#define SHA_NULL_PARAM_CHK(para) \
do { \
if (para == NULL) { \
return ERR_SHA(DRV_ERROR_PARAMETER); \
} \
} while (0)
//
// Functions
//
ck_sha_reg_t *sha_reg = NULL;
#ifndef CONFIG_SHA_SUPPORT_MUL_THREAD
static uint32_t sha_buffer[32];
static uint32_t total[2] = {0x0};
static uint8_t first_cal = 1;
#endif
static uint8_t sha_result[64] = {0x0};
static int32_t sha_set_mode(sha_mode_e mode)
{
sha_reg->SHA_MODE &= ~0x7;
sha_reg->SHA_MODE |= mode;
return 0;
}
static void sha_set_source_message(uint32_t baseaddr)
{
sha_reg->SHA_BASEADDR = baseaddr;
}
static void sha_set_dest_message(uint32_t destaddr)
{
sha_reg->SHA_DESTADDR = destaddr;
}
static void sha_enable_without_count(void)
{
sha_reg->SHA_MODE |= 1<<25;
}
static void sha_disable_without_count(void)
{
sha_reg->SHA_MODE &= ~(1<<25);
}
static void sha_set_message_count(uint32_t count)
{
sha_reg->SHA_COUNTER0 = count;
sha_reg->SHA_COUNTER1 = 0;
}
static int32_t sha_enable_initial(void)
{
sha_reg->SHA_MODE |= 1 << SHA_INIT_OFFSET;
return 0;
}
static int32_t sha_disable_initial(void)
{
sha_reg->SHA_MODE &= ~(1 << SHA_INIT_OFFSET);
return 0;
}
static int32_t sha_enable_calculate(void)
{
sha_reg->SHA_CON |= 1;
return 0;
}
static int32_t sha_message_done(void)
{
volatile uint32_t value = sha_reg->SHA_CON;
while(value & 0x1) {
mdelay(1);
value = sha_reg->SHA_CON;
}
return 0;
}
static void sha_new_encode(void)
{
sha_reg->SHA_INTSTATE = 0;
sha_reg->SHA_MODE = 0;
}
#ifdef CONFIG_SHA_SUPPORT_MUL_THREAD
static int32_t sha_restore_context(sha_handle_t handle, uint32_t *data)
{
uint32_t *result = (uint32_t *)&sha_reg->SHA_H0L;
uint8_t i;
for (i = 0; i < 16; i++) {
result[i] = data[i];
}
return 0;
}
static int32_t sha_save_context(sha_handle_t handle, uint32_t *data)
{
uint32_t *result = (uint32_t *)&sha_reg->SHA_H0L;
uint8_t i;
for (i = 0; i < 16; i++) {
data[i] = result[i];
}
return 0;
}
#endif
static inline void sha_reverse_order(uint8_t *pdata, int32_t length)
{
uint8_t input_data[length];
uint8_t result[length];
uint32_t tmp = 0;
int32_t i = 0;
memcpy((void *)input_data, (void *)pdata, length);
for (i = 0; i < length; i++) {
tmp = i >> 2;
tmp = tmp << 3;
result[i] = input_data[tmp + 3 - i];
}
memcpy((void *)pdata, (void *)result, length);
}
/**
\brief Initialize SHA Interface. 1. Initializes the resources needed for the SHA interface 2.registers event callback function
\param[in] context Pointer to the buffer store the sha context
\param[in] cb_event Pointer to \ref sha_event_cb_t
\return return sha handle if success
*/
sha_handle_t csi_sha_initialize(int32_t idx, void *context, sha_event_cb_t cb_event)
{
(void)idx;
if (idx < 0 || idx >= CONFIG_SHA_NUM) {
return NULL;
}
#ifdef CONFIG_SHA_SUPPORT_MUL_THREAD
uint32_t base = 0u;
uint32_t irq;
/* obtain the sha information */
target_get_sha(0, &base, &irq);
ck_sha_priv_t *sha_priv = context;
memset(sha_priv->state, 0, sizeof(sha_priv->state));
sha_priv->total = 0;
sha_priv->first_cal = 1;
#else
uint32_t base = 0u;
uint32_t irq;
/* obtain the sha information */
int32_t real_idx = target_get_sha(idx, &base, &irq);
if (real_idx != idx) {
return NULL;
}
ck_sha_priv_t *sha_priv = &sha_handle[idx];
#endif
sha_priv->base = base;
sha_priv->irq = irq;
/* initialize the sha context */
sha_priv->cb = cb_event;
sha_priv->status.busy = 0;
return (sha_handle_t)sha_priv;
}
/**
\brief De-initialize SHA Interface. stops operation and releases the software resources used by the interface
\param[in] handle sha handle to operate.
\return error code
*/
int32_t csi_sha_uninitialize(sha_handle_t handle)
{
SHA_NULL_PARAM_CHK(handle);
ck_sha_priv_t *sha_priv = handle;
sha_priv->cb = NULL;
return 0;
}
/**
\brief Get driver capabilities.
\param[in] idx device id
\return \ref sha_capabilities_t
*/
sha_capabilities_t csi_sha_get_capabilities(int32_t idx)
{
if (idx < 0 || idx >= CONFIG_SHA_NUM) {
sha_capabilities_t ret;
memset(&ret, 0, sizeof(sha_capabilities_t));
return ret;
}
return driver_capabilities;
}
/**
\brief config sha mode.
\param[in] handle sha handle to operate.
\param[in] mode \ref sha_mode_e
\param[in] endian \ref sha_endian_mode_e
\return error code
*/
int32_t csi_sha_config(sha_handle_t handle, sha_mode_e mode, sha_endian_mode_e endian_mode)
{
SHA_NULL_PARAM_CHK(handle);
ck_sha_priv_t *sha_priv = handle;
sha_reg = (ck_sha_reg_t *)(sha_priv->base);
/* config the sha mode */
switch (mode) {
case SHA_MODE_512_256:
case SHA_MODE_512_224:
return ERR_SHA(DRV_ERROR_UNSUPPORTED);
case SHA_MODE_1:
case SHA_MODE_224:
case SHA_MODE_256:
case SHA_MODE_384:
case SHA_MODE_512:
sha_priv->mode = mode;
break;
default:
return ERR_SHA(SHA_ERROR_MODE);
}
if (endian_mode == SHA_ENDIAN_MODE_LITTLE) {
return ERR_SHA(DRV_ERROR_UNSUPPORTED);
} else if (endian_mode == SHA_ENDIAN_MODE_BIG) {
;
} else {
return ERR_SHA(SHA_ERROR_ENDIAN);
}
return 0;
}
/**
\brief start the engine
\param[in] handle sha handle to operate.
\param[in] context Pointer to the sha context.
\return error code
*/
int32_t csi_sha_start(sha_handle_t handle, void *context)
{
SHA_NULL_PARAM_CHK(handle);
ck_sha_priv_t *sha_priv = handle;
sha_priv->status.busy = 1;
sha_new_encode();
sha_set_mode(sha_priv->mode);
#ifdef CONFIG_SHA_SUPPORT_MUL_THREAD
memset(sha_priv->sha_buffer, 0, sizeof(sha_priv->sha_buffer));
memset(sha_priv->state, 0, sizeof(sha_priv->state));
sha_priv->first_cal = 1;
sha_priv->total = 0;
#endif
return 0;
}
/**
\brief updata the engine
\param[in] handle sha handle to operate.
\param[in] context Pointer to the sha context.
\param[in] input Pointer to the Source data
\param[in] len the data len
\return error code
*/
int32_t csi_sha_update(sha_handle_t handle, void *context, const void *input, uint32_t len)
{
SHA_NULL_PARAM_CHK(handle);
SHA_NULL_PARAM_CHK(input);
if (len <= 0) {
return ERR_SHA(DRV_ERROR_PARAMETER);
}
ck_sha_priv_t *sha_priv = handle;
sha_reg = (ck_sha_reg_t *)(sha_priv->base);
uint8_t total_len_num;
uint32_t block_size;
if (sha_priv->mode < 4) {
block_size = 64;
total_len_num = 2;
} else {
block_size = 128;
total_len_num = 4;
}
#ifdef CONFIG_SHA_SUPPORT_MUL_THREAD
uint32_t *sha_buffer = sha_priv->sha_buffer;
uint8_t first_cal = sha_priv->first_cal;
sha_set_mode(sha_priv->mode);
uint32_t left = sha_priv->total & (block_size - 1);
uint32_t fill = block_size - left;
uint32_t total_length = sha_priv->total << 3;
uint32_t index = left >> 2;
if (left & 0x3) {
index++;
}
sha_priv->total += len;
sha_priv->total &= 0xffffffff;
#else
uint32_t left = total[0] & (block_size - 1);
uint32_t fill = block_size - left;
uint32_t total_length = total[0] << 3;
uint32_t index = left >> 2;
if (left & 0x3) {
index++;
}
total[0] += len;
total[0] &= 0xffffffff;
#endif
uint8_t *p = (uint8_t *)input;
/* when the text is not aligned by block and len > fill */
if (left && len >= fill) {
if (finish_flag) {
#ifdef CONFIG_SHA_SUPPORT_MUL_THREAD
memset(((uint8_t *)sha_buffer + left), 0x0, sizeof(sha_priv->sha_buffer) - left);
#else
memset(((uint8_t *)sha_buffer + left), 0x0, sizeof(sha_buffer) - left);
#endif
sha_buffer[index + total_len_num - 1] = total_length;
sha_disable_without_count();
sha_set_message_count(left << 3);
} else {
memcpy((void *)(((uint8_t *)sha_buffer) + left), p, fill);
p += fill;
sha_enable_without_count();
sha_set_message_count(block_size << 3);
}
sha_set_source_message((uint32_t)sha_buffer);
sha_set_dest_message((uint32_t)sha_result);
if (first_cal == 0) {
sha_enable_initial();
} else {
sha_disable_initial();
}
#ifdef CONFIG_SHA_SUPPORT_MUL_THREAD
sha_restore_context(handle, (uint32_t *)sha_priv->state);
#endif
sha_enable_calculate();
sha_message_done();
#ifdef CONFIG_SHA_SUPPORT_MUL_THREAD
sha_save_context(handle, (uint32_t *)sha_priv->state);
#endif
len -= fill;
left = 0;
#ifdef CONFIG_SHA_SUPPORT_MUL_THREAD
sha_priv->first_cal = 0;
first_cal = 0;
#else
first_cal = 0;
#endif
}
/* calculate the hash by block */
while (len >= block_size) {
if (finish_flag) {
#ifdef CONFIG_SHA_SUPPORT_MUL_THREAD
memset(sha_buffer, 0, sizeof(sha_priv->sha_buffer));
#else
memset(sha_buffer, 0, sizeof(sha_buffer));
#endif
sha_buffer[total_len_num - 1] = total_length;
sha_set_source_message((uint32_t)sha_buffer);
sha_disable_without_count();
sha_set_message_count(0);
} else {
memcpy(sha_buffer, p, block_size);
sha_set_source_message((uint32_t)sha_buffer);
sha_enable_without_count();
sha_set_message_count(block_size << 3);
p += block_size;
}
sha_set_dest_message((uint32_t)sha_result);
if (first_cal == 0) {
sha_enable_initial();
} else {
sha_disable_initial();
}
#ifdef CONFIG_SHA_SUPPORT_MUL_THREAD
sha_restore_context(handle, (uint32_t *)sha_priv->state);
#endif
sha_enable_calculate();
sha_message_done();
#ifdef CONFIG_SHA_SUPPORT_MUL_THREAD
sha_save_context(handle, (uint32_t *)sha_priv->state);
#endif
#ifdef CONFIG_SHA_SUPPORT_MUL_THREAD
sha_priv->first_cal = 0;
first_cal = 0;
#else
first_cal = 0;
#endif
len -= block_size;
}
/* when the text is not aligned by block and len < fill */
if (len > 0) {
memcpy((void *)(((uint8_t *)sha_buffer) + left), p, len);
}
sha_priv->status.busy = 0;
return 0;
}
/**
\brief finish the engine
\param[in] handle sha handle to operate.
\param[in] context Pointer to the sha context.
\param[out] output Pointer to the dest data
\return error code
*/
int32_t csi_sha_finish(sha_handle_t handle, void *context, void *output)
{
SHA_NULL_PARAM_CHK(handle);
SHA_NULL_PARAM_CHK(output);
ck_sha_priv_t *sha_priv = handle;
uint32_t block_size;
if (sha_priv->mode < 4) {
block_size = 64;
} else {
block_size = 128;
}
#ifdef CONFIG_SHA_SUPPORT_MUL_THREAD
uint32_t last = sha_priv->total & (block_size - 1);
#else
uint32_t last = total[0] & (block_size - 1);
#endif
uint32_t padn = block_size - last;
finish_flag = 1;
csi_sha_update(handle, NULL, output, padn);
uint8_t result_len = 20;
/* convert the data endian according the sha mode */
if (sha_priv->mode == SHA_MODE_1) {
result_len = 20;
} else if (sha_priv->mode == SHA_MODE_224) {
result_len = 28;
} else if (sha_priv->mode == SHA_MODE_256) {
result_len = 32;
} else if (sha_priv->mode == SHA_MODE_512) {
result_len = 64;
} else if (sha_priv->mode == SHA_MODE_384) {
result_len = 48;
}
sha_reverse_order(sha_result, result_len);
memcpy((uint8_t*)output, sha_result, result_len);
finish_flag = 0;
#ifdef CONFIG_SHA_SUPPORT_MUL_THREAD
memset(sha_priv->sha_buffer, 0, sizeof(sha_priv->sha_buffer));
sha_priv->first_cal = 1;
sha_priv->total = 0;
#else
memset(sha_buffer, 0, sizeof(sha_buffer));
first_cal = 1;
total[0] = 0;
#endif
return 0;
}
/**
\brief Get SHA status.
\param[in] handle sha handle to operate.
\return SHA status \ref sha_status_t
*/
sha_status_t csi_sha_get_status(sha_handle_t handle)
{
if (handle == NULL) {
sha_status_t ret;
memset(&ret, 0, sizeof(sha_status_t));
return ret;
}
ck_sha_priv_t *sha_priv = handle;
return sha_priv->status;
}

View file

@ -0,0 +1,705 @@
/*
* Copyright (C) 2017 C-SKY Microsystems Co., Ltd. All rights reserved.
*
* 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 ck_sha_v2.c
* @brief CSI Source File for SHA Driver
* @version V1.0
* @date 02. June 2017
******************************************************************************/
#include <csi_config.h>
#include <stdio.h>
#include <string.h>
#include <stdbool.h>
#include "drv_sha.h"
#include "ck_sha_v2.h"
#include "csi_core.h"
#ifndef CONFIG_SHA_SUPPORT_MUL_THREAD
#define CONFIG_SHA_SUPPORT_MUL_THREAD 1
#endif
extern int32_t target_get_sha_count(void);
extern int32_t target_get_sha(int32_t idx, uint32_t *base, uint32_t *irq);
typedef struct {
uint32_t base;
uint32_t irq;
sha_event_cb_t cb;
sha_status_t status;
sha_mode_e mode;
sha_endian_mode_e endian;
#ifdef CONFIG_SHA_SUPPORT_MUL_THREAD
uint8_t state[64];
uint8_t sha_buffer[128];
uint32_t total;
uint32_t last_left;
#endif
} ck_sha_priv_t;
#ifndef CONFIG_SHA_SUPPORT_MUL_THREAD
static ck_sha_priv_t sha_handle[CONFIG_SHA_NUM];
#endif
static uint32_t g_sha_context[CONFIG_SHA_NUM];
bool finish_flag = 0;
/* Driver Capabilities */
static const sha_capabilities_t driver_capabilities = {
.sha1 = 1, /* sha1 mode */
.sha224 = 1, /* sha224 mode */
.sha256 = 1, /* sha256 mode */
.sha384 = 1, /* sha384 mode */
.sha512 = 1, /* sha512 mode */
.sha512_224 = 0, /* sha512_224 mode */
.sha512_256 = 0, /* sha512_256 mode */
.endianmode = 1, /* endian mode */
.interruptmode = 1 /* interrupt mode */
};
#define ERR_SHA(errno) (CSI_DRV_ERRNO_SHA_BASE | errno)
#define SHA_NULL_PARAM_CHK(para) \
do { \
if (para == NULL) { \
return ERR_SHA(DRV_ERROR_PARAMETER); \
} \
} while (0)
//
// Functions
//
ck_sha_reg_t *sha_reg = NULL;
volatile static uint8_t sha_int_flag = 1;
static int32_t sha_set_mode(sha_mode_e mode)
{
sha_reg->SHA_CON &= ~0x7;
sha_reg->SHA_CON |= mode;
return 0;
}
#ifndef CONFIG_SHA_BLOCK_MODE
static int32_t sha_enable_interrupt(void)
{
sha_reg->SHA_CON |= 1 << SHA_INT_ENABLE_OFFSET;
return 0;
}
#ifndef CONFIG_SHA_SUPPORT_MUL_THREAD
static int32_t sha_disable_interrupt(void)
{
sha_reg->SHA_CON &= ~(1 << SHA_INT_ENABLE_OFFSET);
return 0;
}
#endif
#endif
static void sha_clear_interrupt(void)
{
sha_reg->SHA_INTSTATE = 0;
}
static int32_t sha_enable_initial(void)
{
sha_reg->SHA_CON |= 1 << SHA_INIT_OFFSET;
return 0;
}
static int32_t sha_enable_calculate(void)
{
sha_reg->SHA_CON |= 1 << SHA_CAL_OFFSET;
return 0;
}
#ifdef CONFIG_SHA_BLOCK_MODE
static int32_t sha_message_done(void)
{
while((sha_reg->SHA_CON & 0x40));
return 0;
}
#endif
static int32_t sha_select_endian_mode(sha_endian_mode_e mode)
{
sha_reg->SHA_CON &= ~(1 << SHA_ENDIAN_OFFSET);
sha_reg->SHA_CON |= mode << SHA_ENDIAN_OFFSET;
return 0;
}
static int32_t sha_input_data(uint32_t *data, uint32_t length)
{
uint8_t i;
uint32_t tmp;
uint32_t *input_data = (uint32_t *) & (sha_reg->SHA_DATA1);
for (i = 0; i < length; i++) {
memcpy(&tmp, (uint8_t *)(data+i), 4);
*(input_data + i) = tmp;
}
return 0;
}
static int32_t sha_get_data(sha_handle_t handle, uint32_t *data)
{
ck_sha_priv_t *sha_priv = handle;
uint8_t len = 0;
uint8_t i;
uint32_t temp;
uint32_t *result = (uint32_t *)&sha_reg->SHA_H0L;
/* according to different mode to obtain the hash result */
if (sha_priv->mode == SHA_MODE_1 || sha_priv->mode == SHA_MODE_224 || sha_priv->mode == SHA_MODE_256) {
if (sha_priv->mode == SHA_MODE_1) {
len = 5;
} else if (sha_priv->mode == SHA_MODE_224) {
len = 7;
} else if (sha_priv->mode == SHA_MODE_256) {
len = 8;
}
for (i = 0; i < len; i++) {
temp = *(result + i);
memcpy(&data[i], &temp, 4);
}
} else {
if (sha_priv->mode == SHA_MODE_384) {
len = 6;
} else if (sha_priv->mode == SHA_MODE_512) {
len = 8;
}
uint32_t *resulth = (uint32_t *)&sha_reg->SHA_H0H;
for (i = 0; i < len; i++) {
// data[i << 1] = *(resulth + i);
// data[(i << 1) + 1] = *(result + i);
temp = *(resulth + i);
memcpy(&data[i<<1], &temp, 4);
temp = *(result + i);
memcpy(&data[(i<<1)+1], &temp, 4);
}
}
return 0;
}
#ifdef CONFIG_SHA_SUPPORT_MUL_THREAD
static int32_t sha_set_data(sha_handle_t handle, uint32_t *data)
{
ck_sha_priv_t *sha_priv = handle;
uint8_t len = 0;
uint8_t i;
uint32_t *result = (uint32_t *)&sha_reg->SHA_H0L;
/* according to different mode to obtain the hash result */
if (sha_priv->mode == SHA_MODE_1 || sha_priv->mode == SHA_MODE_224 || sha_priv->mode == SHA_MODE_256) {
if (sha_priv->mode == SHA_MODE_1) {
len = 5;
} else if (sha_priv->mode == SHA_MODE_224) {
len = 7;
} else if (sha_priv->mode == SHA_MODE_256) {
len = 8;
}
for (i = 0; i < len; i++) {
*(result + i) = data[i];
}
} else {
if (sha_priv->mode == SHA_MODE_384) {
len = 6;
} else if (sha_priv->mode == SHA_MODE_512) {
len = 8;
}
uint32_t *resulth = (uint32_t *)&sha_reg->SHA_H0H;
for (i = 0; i < len; i++) {
*(resulth + i) = data[i << 1];
*(result + i) = data[(i << 1) + 1] ;
}
}
return 0;
}
#endif
static inline void sha_reverse_order(uint8_t *pdata, int32_t length)
{
uint8_t input_data[length];
uint8_t result[length];
uint32_t tmp = 0;
int32_t i = 0;
memcpy((void *)input_data, (void *)pdata, length);
for (i = 0; i < length; i++) {
tmp = i >> 2;
tmp = tmp << 3;
result[i] = input_data[tmp + 3 - i];
}
memcpy((void *)pdata, (void *)result, length);
}
void ck_sha_irqhandler(int32_t idx)
{
sha_int_flag = 0;
sha_clear_interrupt(); //clear sha interrupt
#ifndef CONFIG_SHA_SUPPORT_MUL_THREAD
ck_sha_priv_t *sha_priv = &sha_handle[idx];
#else
ck_sha_priv_t *sha_priv = (ck_sha_priv_t *)g_sha_context[idx];
#endif
if (finish_flag != 0) {
if (sha_priv->cb != NULL) {
sha_priv->cb(idx, SHA_EVENT_COMPLETE); //execute the callback function
}
}
}
/**
\brief Initialize SHA Interface. 1. Initializes the resources needed for the SHA interface 2.registers event callback function
\param[in] context Pointer to the buffer store the sha context
\param[in] cb_event Pointer to \ref sha_event_cb_t
\return return sha handle if success
*/
sha_handle_t csi_sha_initialize(int32_t idx, void *context, sha_event_cb_t cb_event)
{
(void)idx;
if (idx < 0 || idx >= CONFIG_SHA_NUM) {
return NULL;
}
#ifdef CONFIG_SHA_SUPPORT_MUL_THREAD
uint32_t base = 0u;
uint32_t irq;
/* obtain the sha information */
target_get_sha(0, &base, &irq);
ck_sha_priv_t *sha_priv = context;
memset(sha_priv->state, 0, sizeof(sha_priv->state));
sha_priv->last_left = 0;
sha_priv->total = 0;
g_sha_context[0] = (uint32_t)context;
#else
uint32_t base = 0u;
uint32_t irq;
/* obtain the sha information */
int32_t real_idx = target_get_sha(idx, &base, &irq);
if (real_idx != idx) {
return NULL;
}
ck_sha_priv_t *sha_priv = &sha_handle[idx];
#endif
sha_priv->base = base;
sha_priv->irq = irq;
/* initialize the sha context */
sha_priv->cb = cb_event;
sha_priv->status.busy = 0;
#ifndef CONFIG_SHA_BLOCK_MODE
csi_vic_enable_irq(sha_priv->irq);
#endif
return (sha_handle_t)sha_priv;
}
/**
\brief De-initialize SHA Interface. stops operation and releases the software resources used by the interface
\param[in] handle sha handle to operate.
\return error code
*/
int32_t csi_sha_uninitialize(sha_handle_t handle)
{
SHA_NULL_PARAM_CHK(handle);
ck_sha_priv_t *sha_priv = handle;
sha_priv->cb = NULL;
#ifndef CONFIG_SHA_SUPPORT_MUL_THREAD
#ifndef CONFIG_SHA_BLOCK_MODE
sha_disable_interrupt();
csi_vic_disable_irq(sha_priv->irq);
#endif
#endif
return 0;
}
/**
\brief Get driver capabilities.
\param[in] idx device id
\return \ref sha_capabilities_t
*/
sha_capabilities_t csi_sha_get_capabilities(int32_t idx)
{
if (idx < 0 || idx >= CONFIG_SHA_NUM) {
sha_capabilities_t ret;
memset(&ret, 0, sizeof(sha_capabilities_t));
return ret;
}
return driver_capabilities;
}
/**
\brief config sha mode.
\param[in] handle sha handle to operate.
\param[in] mode \ref sha_mode_e
\param[in] endian \ref sha_endian_mode_e
\return error code
*/
int32_t csi_sha_config(sha_handle_t handle, sha_mode_e mode, sha_endian_mode_e endian_mode)
{
SHA_NULL_PARAM_CHK(handle);
ck_sha_priv_t *sha_priv = handle;
sha_reg = (ck_sha_reg_t *)(sha_priv->base);
/* config the sha mode */
switch (mode) {
case SHA_MODE_512_256:
case SHA_MODE_512_224:
return ERR_SHA(DRV_ERROR_UNSUPPORTED);
case SHA_MODE_1:
case SHA_MODE_224:
case SHA_MODE_256:
case SHA_MODE_384:
case SHA_MODE_512:
sha_priv->mode = mode;
break;
default:
return ERR_SHA(SHA_ERROR_MODE);
}
sha_set_mode(mode);
/*config the sha endian mode */
if (endian_mode == SHA_ENDIAN_MODE_LITTLE) {
sha_priv->endian = endian_mode;
sha_select_endian_mode(endian_mode);
} else if (endian_mode == SHA_ENDIAN_MODE_BIG) {
sha_priv->endian = endian_mode;
sha_select_endian_mode(endian_mode);
} else {
return ERR_SHA(SHA_ERROR_ENDIAN);
}
#ifndef CONFIG_SHA_BLOCK_MODE
sha_enable_interrupt();
#endif
return 0;
}
/**
\brief start the engine
\param[in] handle sha handle to operate.
\param[in] context Pointer to the sha context.
\return error code
*/
int32_t csi_sha_start(sha_handle_t handle, void *context)
{
SHA_NULL_PARAM_CHK(handle);
ck_sha_priv_t *sha_priv = handle;
sha_enable_initial();
sha_priv->status.busy = 1;
#ifdef CONFIG_SHA_SUPPORT_MUL_THREAD
sha_get_data(handle, (uint32_t *)sha_priv->state);
#endif
return 0;
}
/**
\brief updata the engine
\param[in] handle sha handle to operate.
\param[in] context Pointer to the sha context.
\param[in] input Pointer to the Source data
\param[in] len the data len
\return error code
*/
#ifndef CONFIG_SHA_SUPPORT_MUL_THREAD
static uint8_t sha_buffer[128];
static uint32_t total[2] = {0x0};
static uint32_t last_left = 0;
#endif
int32_t csi_sha_update(sha_handle_t handle, void *context, const void *input, uint32_t len)
{
SHA_NULL_PARAM_CHK(handle);
SHA_NULL_PARAM_CHK(input);
if (len <= 0) {
return ERR_SHA(DRV_ERROR_PARAMETER);
}
g_sha_context[0] = (uint32_t)handle;
ck_sha_priv_t *sha_priv = handle;
sha_reg = (ck_sha_reg_t *)(sha_priv->base);
uint32_t block_size;
if (sha_priv->mode < 4) {
block_size = 64;
} else {
block_size = 128;
}
#ifdef CONFIG_SHA_SUPPORT_MUL_THREAD
uint8_t *sha_buffer = sha_priv->sha_buffer;
uint32_t last_left = sha_priv->last_left;
sha_set_mode(sha_priv->mode);
uint32_t left = sha_priv->total & (block_size - 1);
uint32_t fill = block_size - left;
uint32_t total_length = sha_priv->total << 3;
sha_priv->total += len;
sha_priv->total &= 0xffffffff;
uint32_t word_left = sha_priv->total & 0x3;
#else
uint32_t left = total[0] & (block_size - 1);
uint32_t fill = block_size - left;
uint32_t total_length = total[0] << 3;
total[0] += len;
total[0] &= 0xffffffff;
uint32_t word_left = total[0] & 0x3;
#endif
uint8_t temp_data[4];
uint32_t j;
if (finish_flag) {
/*calculate the final word*/
for (j = 0; j < 4; j++) {
temp_data[j] = (total_length >> (8 * j)) & 0xff;
}
}
uint8_t *p = (uint8_t *)input;
/* when the text is not aligned by block and len > fill */
if (left && len >= fill) {
if (finish_flag) {
if (sha_priv->endian == SHA_ENDIAN_MODE_BIG) {
memset(&sha_buffer[left], 0x0, len);
sha_buffer[left] = 0x80;
for (j=0; j<4; j++) {
sha_buffer[left + len - 4 + j] = temp_data[3 - j];
}
} else {
memset(&sha_buffer[left + 4 - last_left], 0x0, len - 4 + last_left);
sha_buffer[left - last_left + 3 - last_left] = 0x80;
for (j = 1; j < 4 - last_left; j++) {
sha_buffer[left - last_left + 3 - last_left - j] = 0x00;
}
for (j=0; j<4; j++) {
sha_buffer[left + len - 4 + j] = temp_data[j];
}
}
} else {
if (last_left && sha_priv->endian == SHA_ENDIAN_MODE_LITTLE) {
uint32_t i;
for (i = 0; i < 4 - last_left; i++) {
*(sha_buffer + left + 3 - last_left - i) = *((uint8_t *)p + 3 - last_left - i);
}
fill = fill - 4 + last_left;
p = (p + 4 - last_left);
}
else if (last_left) {
memcpy((void *)(sha_buffer + left + 4 - last_left), p, fill);
} else {
memcpy((void *)(sha_buffer + left), p, fill);
}
p += fill;
}
/* set the input data */
#ifdef CONFIG_SHA_SUPPORT_MUL_THREAD
sha_set_data(handle, (uint32_t *)sha_priv->state);
#endif
sha_input_data((uint32_t *)sha_buffer, block_size >> 2);
sha_enable_calculate();
#ifdef CONFIG_SHA_BLOCK_MODE
sha_message_done();
#else
while (sha_int_flag);
sha_int_flag = 1;
#endif
#ifdef CONFIG_SHA_SUPPORT_MUL_THREAD
sha_get_data(handle, (uint32_t *)sha_priv->state);
#endif
len -= fill;
left = 0;
} else {
if (finish_flag) {
#ifdef CONFIG_SHA_SUPPORT_MUL_THREAD
memset(sha_buffer, 0, sizeof(sha_priv->sha_buffer));
#else
memset(sha_buffer, 0, sizeof(sha_buffer));
#endif
if (sha_priv->endian == SHA_ENDIAN_MODE_BIG) {
sha_buffer[0] = 0x80;
for (j = 0; j < 4; j++) {
sha_buffer[block_size - 4 + j] = temp_data[3 - j];
}
} else {
sha_buffer[3 - last_left] = 0x80;
for (j = 0; j < 4; j++) {
sha_buffer[block_size - 4 + j] = temp_data[j];
}
}
}
}
/* calculate the hash by block */
while (len >= block_size) {
#ifdef CONFIG_SHA_SUPPORT_MUL_THREAD
sha_set_data(handle, (uint32_t *)sha_priv->state);
#endif
if (finish_flag) {
if (fill == block_size) {
sha_input_data((uint32_t *)sha_buffer, block_size >> 2);
} else {
sha_input_data((uint32_t *)&sha_buffer[block_size], block_size >> 2);
}
}
else {
sha_input_data((uint32_t *)p, block_size >> 2);
p += block_size;
}
sha_enable_calculate();
#ifdef CONFIG_SHA_BLOCK_MODE
sha_message_done();
#else
while (sha_int_flag);
sha_int_flag = 1;
#endif
#ifdef CONFIG_SHA_SUPPORT_MUL_THREAD
sha_get_data(handle, (uint32_t *)sha_priv->state);
#endif
len -= block_size;
}
/* when the text is not aligned by block and len < fill */
if (len > 0) {
if (sha_priv->endian == SHA_ENDIAN_MODE_BIG || word_left == 0) {
memcpy((void *)(sha_buffer + left), p, len);
} else {
memcpy((void *)(sha_buffer + left), p, len + 4 - word_left);
#ifdef CONFIG_SHA_SUPPORT_MUL_THREAD
sha_priv->last_left = word_left;
#else
last_left = word_left;
#endif
}
}
sha_priv->status.busy = 0;
return 0;
}
/**
\brief finish the engine
\param[in] handle sha handle to operate.
\param[in] context Pointer to the sha context.
\param[out] output Pointer to the dest data
\return error code
*/
//static uint32_t total_length;
int32_t csi_sha_finish(sha_handle_t handle, void *context, void *output)
{
SHA_NULL_PARAM_CHK(handle);
SHA_NULL_PARAM_CHK(output);
ck_sha_priv_t *sha_priv = handle;
uint32_t block_size;
uint8_t message_len;
if (sha_priv->mode < 4) {
block_size = 64;
message_len = 8;
} else {
block_size = 128;
message_len = 16;
}
#ifdef CONFIG_SHA_SUPPORT_MUL_THREAD
uint32_t last = sha_priv->total & (block_size - 1);
uint32_t padn = (last < (block_size - message_len)) ? (block_size - last) : (block_size + block_size - last);
#else
uint32_t last = total[0] & (block_size - 1);
uint32_t padn = (last < (block_size - message_len)) ? (block_size - last) : (block_size + block_size - last);
#endif
finish_flag = 1;
csi_sha_update(handle, NULL, output, padn);
/* get the hash result */
sha_get_data(handle, (uint32_t *)output);
uint8_t *p = output;
/* convert the data endian according the sha mode */
if (sha_priv->mode == SHA_MODE_1) {
sha_reverse_order(p, 20);
} else if (sha_priv->mode == SHA_MODE_224) {
sha_reverse_order(p, 28);
} else if (sha_priv->mode == SHA_MODE_256) {
sha_reverse_order(p, 32);
} else if (sha_priv->mode == SHA_MODE_512) {
sha_reverse_order(p, 64);
} else if (sha_priv->mode == SHA_MODE_384) {
sha_reverse_order(p, 48);
}
#ifdef CONFIG_SHA_SUPPORT_MUL_THREAD
sha_priv->total = 0;
sha_priv->last_left = 0;
#else
total[0] = 0;
last_left = 0;
#endif
finish_flag = 0;
return 0;
}
/**
\brief Get SHA status.
\param[in] handle sha handle to operate.
\return SHA status \ref sha_status_t
*/
sha_status_t csi_sha_get_status(sha_handle_t handle)
{
if (handle == NULL) {
sha_status_t ret;
memset(&ret, 0, sizeof(sha_status_t));
return ret;
}
ck_sha_priv_t *sha_priv = handle;
return sha_priv->status;
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,742 @@
/* ---------------------------------------------------------------------------
* Copyright (C) 2016 CSKY Limited. All rights reserved.
*
* Redistribution and use of this software 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 CSKY Ltd. nor the names of CSKY's contributors may
* be used to endorse or promote products derived from this software without
* specific prior written permission of CSKY Ltd.
*
* 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 THE COPYRIGHT OWNER OR CONTRIBUTORS
* 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.
* -------------------------------------------------------------------------- */
/******************************************************************************
* @file
* @brief
* @version V1.0
* @date
******************************************************************************/
#include <csi_config.h>
#include <stdint.h>
#include <stdbool.h>
#include <stddef.h>
#include "csi_core.h"
#include "drv_spu.h"
#include "ck_spu.h"
#include "soc.h"
#include "spu_pin_planning.h"
#define ERR_SPU(errno) (CSI_DRV_ERRNO_SPU_BASE | errno)
extern spu_pgpio_info_t get_pgpio_info(uint32_t spu_idx, uint8_t pgpio);
extern void ck_spu_usart_irqhandler(int32_t idx,spu_dev_signal_e signal);
extern void ck_spu_spi_irqhandler(int32_t idx,spu_dev_signal_e signal);
extern void ck_spu_i2c_irqhandler(int32_t idx,spu_dev_signal_e signal);
extern void ck_spu_can_irqhandler(int32_t idx,spu_dev_signal_e signal);
//------------------------------------------
// data private
//------------------------------------------
typedef struct {
uint32_t base;
uint32_t irq;
uint32_t clk_en_vec;
bool clk_en;
uint32_t prog_used;
uint32_t usart_func_index_base;
uint32_t spi_func_index_base;
uint32_t i2c_func_index_base;
uint32_t can_func_index_base;
} ck_spu_priv_t;
static ck_spu_priv_t spu_instance[CONFIG_SPU_NUM];
static const spu_capabilities_t spu_capabilities = {
.spu_usart = 1, //supports USART device
.spu_spi = 1, //supports SPI device
.spu_i2c = 1, //supports I2C device
.spu_can = 0, //supports CAN device
};
//usart function
#define SPU_USART_FUNC_WORDS 180
#define SPU_USART_FUNC_BYTES SPU_USART_FUNC_WORDS*4
const static int32_t SPU_USART_FUNC_INDEX[16] = {
0x00000000,0x00000090,0x000000ba,0x00000000,
0x00000000,0x000000d8,0x00000184,0x00000000,
0x00000000,0x00000000,0x00000000,0x00000000,
0x00000000,0x00000000,0x00000000,0x00000000,
};
const static int32_t SPU_USART_FUNC[180] = {
0x2000d84d,0x3acd74c8,0xd80d082c,0xd82d2003,
0xe0002004,0x3ac800ef,0x4b620817,0x08083ac9,
0x08053aca,0x080a3acb,0x08093acc,0x36003ba4,
0xb680a664,0x3b848ea1,0x35010403,0x714c3500,
0x23006d14,0x44814362,0x6420c104,0xe00003ce,
0x0c1100db,0x2002d8ed,0xdced3fa3,0x040b2002,
0x6024c120,0xc1243cbd,0x03d46420,0x08033ac8,
0x37002303,0xc1466d8c,0x751d6420,0x6dde4ff0,
0x3c40691c,0x34010c04,0x6420c164,0x4c20c000,
0x2000d84d,0xd80d4a50,0xd82d2003,0xe0002004,
0x080300a5,0x040213dd,0x34ff13dd,0x6420c104,
0xc1466d88,0xc0006420,0x340e4c20,0x6420c144,
0x2002d8ed,0xdced3fa2,0x3fd22002,0x34010804,
0x6420c164,0x4c20c000,0x2000d8cd,0x4b6274d8,
0xc1003420,0x3ec86022,0x2300081f,0x7091610e,
0x08043ec9,0x0c0a3eca,0x35003ba4,0xb540b561,
0x3cd09580,0x7491082a,0x34010411,0x710c2b00,
0x3ecb6908,0x3c400804,0x04030820,0x0c1d3c40,
0x68906d12,0x610e0403,0xd80d7091,0xd82d2003,
0xe0002004,0xd88d006f,0x2c002001,0x2001dc8d,
0x0072e000,0xd8ed0c06,0x3fa12002,0x2002dced,
0x4ed012b4,0x040a6d58,0x2002d8ed,0xdced3fa4,
0x12ad2002,0x230374d8,0x751d6d4c,0x6dde4ff0,
0x3c40691c,0x34010c04,0x6420c164,0x6420c145,
0x4c20c000,0x2000d8cd,0x3ec874d8,0x23030802,
0x26004ed2,0x715912a4,0x6027c100,0x6dde6dd4,
0x0c073f40,0x2002d8ed,0xdced3fa5,0x040a2002,
0x2001d88d,0x080a3c40,0x2002d8ed,0xdced3fa0,
0xc1402002,0x3e806026,0x11d30403,0x751d6d8c,
0x6dde4ff0,0x3c40691c,0x34010c04,0x6420c164,
0x6420c146,0x4c20c000,0x75457501,0x783c6552,
0x69004898,0x611449b0,0x94804482,0xdc0d2000,
0x783c1006,0x75115981,0x755448b0,0x783c6514,
0x69044898,0x611449b0,0xb4404482,0xdc2d2100,
0x783c1008,0x75115981,0x755448b0,0x783c6515,
0x31003000,0x33003200,0x35003400,0x37003600,
0xc002105a,0xc0006421,0x3aa66022,0xc0023aa8,
0x10d76420,0x5e8d3340,0x24033500,0x6518b4a0,
0x10f40bfd,0x78001014,0x6c036c03,0x6c036c03,
0x10726c03,0x0c0764c2,0x6021c000,0x642bc001,
0xb020100b,0x642bc001,0xb0201009,0x000007fc,
0xc1e71003,0xe1e71201,0xc0e31083,0xc0e31783,
0xc0e35281,0xffffffff,0x00000000,0x6000fff8,
0x000003c2,0x0000040c,0x1324ffbb,0x6c036c03,
0x6c036c03,0x6c036c03,0x6c036c03,0x00000000
};
//spi function
#define SPU_SPI_FUNC_WORDS 816
#define SPU_SPI_FUNC_BYTES SPU_SPI_FUNC_WORDS*4
const static int32_t SPU_SPI_FUNC_INDEX[128]={
0x00000000,0x00000048,0x000000a2,0x00000000,
0x00000000,0x00000000,0x00000000,0x00000000,
0x00000000,0x00000000,0x00000000,0x00000000,
0x00000000,0x00000000,0x00000000,0x00000000,
0x0000016c,0x000001b4,0x0000020e,0x00000000,
0x00000000,0x00000000,0x00000000,0x00000000,
0x00000000,0x00000000,0x00000000,0x00000000,
0x00000000,0x00000000,0x00000000,0x00000000,
0x000002d8,0x000002ee,0x0000036e,0x000003fe,
0x00000000,0x00000000,0x00000000,0x00000000,
0x00000000,0x00000000,0x00000000,0x00000000,
0x00000000,0x00000000,0x00000000,0x00000000,
0x00000498,0x000004ae,0x00000536,0x00000590,
0x00000000,0x00000000,0x00000000,0x00000000,
0x00000000,0x00000000,0x00000000,0x00000000,
0x00000000,0x00000000,0x00000000,0x00000000,
0x0000062a,0x00000634,0x000006ac,0x00000000,
0x00000000,0x00000000,0x00000000,0x00000000,
0x00000000,0x00000000,0x00000000,0x00000000,
0x00000000,0x00000000,0x00000762,0x00000000,
0x00000776,0x00000780,0x000007f8,0x00000000,
0x00000000,0x00000000,0x00000000,0x00000000,
0x00000000,0x00000000,0x00000000,0x00000000,
0x00000000,0x00000000,0x000008ea,0x00000000,
0x000008fe,0x000009a8,0x00000000,0x00000000,
0x00000000,0x00000000,0x00000000,0x00000000,
0x00000000,0x00000000,0x00000000,0x00000000,
0x00000000,0x00000000,0x0000090e,0x00000000,
0x00000a5e,0x00000b08,0x00000000,0x00000000,
0x00000000,0x00000000,0x00000000,0x00000000,
0x00000000,0x00000000,0x00000000,0x00000000,
0x00000000,0x00000000,0x00000b6e,0x00000000
};
const static int32_t SPU_SPI_FUNC[816] = {
0x2001d84d,0x2000d8cd,0x0c0d3ac0,0x6d180093,
0x6421c144,0x2005d80d,0x2006d82d,0x05d5e000,
0x6421c104,0x0c053ac1,0x6d180099,0x6422c144,
0xc1043400,0x34036423,0x6d5800bc,0x6420c144,
0x6423c145,0x4c20c000,0xc1463602,0xd8ed6420,
0x3fc12001,0xd84d0c1b,0x75082000,0x24004c82,
0x6c463100,0x0c023adc,0x70507051,0xc1026c46,
0x68846022,0x2007d80d,0x2008d82d,0x05b5e000,
0x2003d88d,0xdc8d2c00,0x3fc22003,0x34fe0803,
0x34000402,0x6423c104,0xc14601d3,0xc0006423,
0x37004c20,0x2001d84d,0x0c2c3ac0,0x2005d80d,
0x2006d82d,0x0585e000,0x3ac30810,0x340e0805,
0x6423c144,0x34000404,0x6423c104,0x2004d8ed,
0xdced3fa2,0x04162004,0x0577e000,0x6421c104,
0x02a63403,0x2000d8cd,0xc1456d58,0xc1446423,
0xe0006420,0x0c060574,0x2004d8ed,0xdced3fa3,
0x3ac12004,0xd88d0c29,0x3c402003,0x3ac30810,
0x340e0805,0x6423c144,0x34000404,0x6423c104,
0x2004d8ed,0xdced3fa0,0x04162004,0x02b93403,
0x2000d8cd,0xc1456d58,0xc1446423,0xd80d6420,
0xd82d2007,0xe0002008,0x0c06055a,0x2004d8ed,
0xdced3fa1,0x751d2004,0x6dde4ff0,0x3c40691c,
0x34010c04,0x6423c164,0x4c20c000,0x2001d84d,
0x2000d8cd,0x0c0d3ac0,0x6d18038a,0x6421c144,
0x2005d80d,0x2006d82d,0x051fe000,0x6421c104,
0x0c053ac1,0x6d180390,0x6422c144,0xc1043400,
0x340f6423,0x6d5803b3,0x6420c144,0x6423c145,
0x4c20c000,0xc146360e,0xd8ed6420,0x3fc12001,
0xd84d0c1b,0x75082000,0x24004c82,0x6c463100,
0x0c023adc,0x70507051,0xc1026c46,0x68846022,
0x2007d80d,0x2008d82d,0x04ffe000,0x2003d88d,
0xdc8d2c00,0x3fc22003,0x34fe0803,0x34000402,
0x6423c104,0xc14613d1,0xc0006423,0x37004c20,
0x2001d84d,0x0c2c3ac0,0x2005d80d,0x2006d82d,
0x04cfe000,0x3ac30810,0x340e0805,0x6423c144,
0x34000404,0x6423c104,0x2004d8ed,0xdced3fa2,
0x04162004,0x04c1e000,0x6421c104,0x13a2340f,
0x2000d8cd,0xc1456d58,0xc1446423,0xe0006420,
0x0c0604be,0x2004d8ed,0xdced3fa3,0x3ac12004,
0xd88d0c29,0x3c402003,0x3ac30810,0x340e0805,
0x6423c144,0x34000404,0x6423c104,0x2004d8ed,
0xdced3fa0,0x04162004,0x12af340f,0x2000d8cd,
0xc1456d58,0xc1446423,0xd80d6420,0xd82d2007,
0xe0002008,0x0c0604a4,0x2004d8ed,0xdced3fa1,
0x751d2004,0x6dde4ff0,0x3c40691c,0x34010c04,
0x6423c164,0x4c20c000,0xc1043400,0x11bf6423,
0xc1453602,0xc1466423,0xc0006420,0x37004c20,
0x003bea88,0x6420c148,0x2001d84d,0x2000d8cd,
0x0c153ac0,0x2005d80d,0x2006d82d,0x045de000,
0x6421c104,0x6d181193,0x6421c144,0x045fe000,
0xd8ed0c06,0x3fa32004,0x2004dced,0x0c113ac1,
0x6d18118d,0x6422c144,0x2007d80d,0x2008d82d,
0x045de000,0xd8ed0c06,0x3fa12004,0x2004dced,
0x4ff0751d,0x691c6dde,0x0c043c40,0xc1643401,
0x11a26423,0xc1456d58,0xc0006423,0x36024c20,
0x6420c146,0x2001d8ed,0x0c1b3fc1,0x2000d84d,
0x4c827508,0x31002400,0x3adc6c46,0x70510c02,
0x6c467050,0x6022c102,0xd80d6884,0xd82d2007,
0xe0002008,0xd88d0422,0x2c002003,0x2003dc8d,
0x3fc210cf,0x34fe081e,0x0000041d,0x80008803,
0x80008001,0x80009803,0xc0001087,0x80004003,
0x80004001,0x80005003,0xc0001003,0x00000007,
0x8000409f,0x8000c09d,0x8000589f,0xc0001107,
0xc1043400,0xc1466423,0xc0006423,0x37004c20,
0x2001d84d,0x0c203ac0,0x2005d80d,0x2006d82d,
0x03d7e000,0x3ac30810,0x340e0805,0x6423c144,
0x34000404,0x6423c104,0x2004d8ed,0xdced3fa2,
0x040a2004,0xc1043400,0x34026423,0xc14500ae,
0xc1446423,0x3ac16420,0xd88d0c1d,0x3c402003,
0x3ac30810,0x340e0805,0x6423c144,0x34000404,
0x6423c104,0x2004d8ed,0xdced3fa0,0x040a2004,
0xc1043400,0x34026423,0xc14500bd,0xc1446423,
0x751d6420,0x6dde4ff0,0x3c40691c,0x34010c04,
0x6423c164,0x4c20c000,0xc1043400,0x01a66423,
0xc145360e,0xc1466423,0xc0006420,0x37004c20,
0x00d5ea88,0x6420c148,0x2001d84d,0x2000d8cd,
0x0c193ac0,0x2005d80d,0x2006d82d,0x037de000,
0x6421c104,0x6d180192,0x6421c144,0x2005d80d,
0x2006d82d,0x037be000,0xd8ed0c06,0x3fa32004,
0x2004dced,0x0c113ac1,0x6d18019a,0x6422c144,
0x2007d80d,0x2008d82d,0x0379e000,0xd8ed0c06,
0x3fa12004,0x2004dced,0x4ff0751d,0x691c6dde,
0x0c043c40,0xc1643401,0x02a56423,0xc1456d58,
0xc0006423,0x360e4c20,0x6420c146,0x2001d8ed,
0x0c1b3fc1,0x2000d84d,0x4c827508,0x31002400,
0x3adc6c46,0x70510c02,0x6c467050,0x6022c102,
0xd80d6884,0xd82d2007,0xe0002008,0xd88d033e,
0x2c002003,0x2003dc8d,0x3fc202d8,0x34fe0803,
0x34000402,0x6423c104,0x6423c146,0x4c20c000,
0xd84d3700,0x3ac02001,0xd80d0c20,0xd82d2005,
0xe0002006,0x0810030e,0x08053ac3,0xc144340e,
0x04046423,0xc1043400,0xd8ed6423,0x3fa22004,
0x2004dced,0x3400040a,0x6423c104,0x03b2340e,
0x6423c145,0x6420c144,0x0c1d3ac1,0x2003d88d,
0x08103c40,0x08053ac3,0xc144340e,0x04046423,
0xc1043400,0xd8ed6423,0x3fa02004,0x2004dced,
0x3400040a,0x6423c104,0x13be340e,0x6423c145,
0x6420c144,0x4ff0751d,0x691c6dde,0x0c043c40,
0xc1643401,0xc0006423,0x139c4c20,0x6423c144,
0x4c20c000,0xd8cd3700,0xd84d2000,0x3ac02001,
0x13970c20,0xc1446d18,0xd80d6422,0xd82d2005,
0xe0002006,0x080902b6,0x2004d8ed,0xdced3fa2,
0xd88d2004,0x040b2002,0x02b9e000,0xd8ed0c06,
0x3fa32004,0x2004dced,0x02a7e000,0x6422c104,
0x0c063ac1,0x6d181387,0x6421c144,0x751d3700,
0x6dde4ff0,0x3c40691c,0x34010c04,0x6423c164,
0x6d181381,0x6423c144,0x4c20c000,0xd8cd3700,
0xd84d2000,0x3ac02001,0xd80d0c1c,0xd82d2005,
0xe0002006,0x0809027e,0x2004d8ed,0xdced3fa2,
0xd88d2004,0x040b2002,0x0281e000,0xd8ed0c06,
0x3fa32004,0x2004dced,0x026fe000,0x6422c104,
0x0c293ac1,0x4c827518,0x31002400,0x3edc6c46,
0x70510c02,0x6c467050,0x6022c101,0xd80d6884,
0xd82d2007,0xe0002008,0xd88d0268,0x2c002003,
0x2003dc8d,0x08073c40,0x2004d8ed,0xdced3fa0,
0x04092004,0x0263e000,0xd8ed0c06,0x3fa12004,
0x2004dced,0x4ff0751d,0x691c6dde,0x0c043c40,
0xc1643401,0x11956423,0xc1446d18,0xc0006423,
0xd86d4c20,0x2b002005,0x2005dc6d,0xc144118b,
0xc0006423,0x11894c20,0x6423c144,0x4c20c000,
0xd8cd3700,0xd84d2000,0x3ac02001,0x11880c20,
0xc1446d18,0xd80d6422,0xd82d2005,0xe0002006,
0x08090210,0x2004d8ed,0xdced3fa2,0xd88d2004,
0x040b2002,0x0213e000,0xd8ed0c06,0x3fa32004,
0x2004dced,0x0201e000,0x6422c104,0x0c063ac1,
0x6d181098,0x6421c144,0x751d3700,0x6dde4ff0,
0x3c40691c,0x34010c04,0x6423c164,0x6d181092,
0x6423c144,0x4c20c000,0xd8cd3700,0x041e2000,
0xc0001003,0x0000000b,0x8000809f,0x8000009d,
0x8000909f,0xc0001107,0xe0201001,0x80008083,
0x80008081,0x80009881,0xa0009881,0x80004083,
0x80004081,0x80005081,0xd84d6c03,0x3ac02001,
0xd80d0c1c,0xd82d2005,0xe0002006,0x080901ba,
0x2004d8ed,0xdced3fa2,0xd88d2004,0x040b2002,
0x01bde000,0xd8ed0c06,0x3fa32004,0x2004dced,
0x01abe000,0x6422c104,0x0c293ac1,0x4c827518,
0x31002400,0x3edc6c46,0x70510c02,0x6c467050,
0x6022c101,0xd80d6884,0xd82d2007,0xe0002008,
0xd88d01a4,0x2c002003,0x2003dc8d,0x08073c40,
0x2004d8ed,0xdced3fa0,0x04092004,0x019fe000,
0xd8ed0c06,0x3fa12004,0x2004dced,0x4ff0751d,
0x691c6dde,0x0c043c40,0xc1643401,0x009d6423,
0xc1446d18,0xc0006423,0xd86d4c20,0x2b002005,
0x2005dc6d,0xc1440182,0xc0006423,0xd8cd4c20,
0x01842000,0xc1446d18,0xc0006423,0x37004c20,
0x6024c083,0x083c3cdf,0x2000d8cd,0x2001d84d,
0x0c203ac0,0x6d18018c,0x6422c144,0x2005d80d,
0x2006d82d,0x0145e000,0xd8ed0809,0x3fa22004,
0x2004dced,0x2002d88d,0xe000040b,0x0c060148,
0x2004d8ed,0xdced3fa3,0xe0002004,0xc1040136,
0x3ac16422,0x019b0c06,0xc1446d18,0x37006421,
0x4ff0751d,0x691c6dde,0x0c043c40,0xc1643401,
0x02816423,0xc1446d18,0xc0006423,0xd86d4c20,
0x2b002006,0x2006dc6d,0xd8cd028a,0x6d182000,
0x6423c144,0x4c20c000,0xd8cd3700,0xd84d2000,
0x3ac02001,0xd80d0c1c,0xd82d2005,0xe0002006,
0x08090100,0x2004d8ed,0xdced3fa2,0xd88d2004,
0x040b2002,0x0103e000,0xd8ed0c06,0x3fa32004,
0x2004dced,0x00f1e000,0x6422c104,0x0c293ac1,
0x4c827518,0x31002400,0x3edc6c46,0x70510c02,
0x6c467050,0x6022c101,0xd80d6884,0xd82d2007,
0xe0002008,0xd88d00ea,0x2c002003,0x2003dc8d,
0x08073c40,0x2004d8ed,0xdced3fa0,0x04092004,
0x00e5e000,0xd8ed0c06,0x3fa12004,0x2004dced,
0x4ff0751d,0x691c6dde,0x0c043c40,0xc1643401,
0x03946423,0xc1446d18,0xc0006423,0xd8cd4c20,
0x039c2000,0xc1446d18,0xc0006423,0x37004c20,
0x6024c083,0x083c3cdf,0x2000d8cd,0x2001d84d,
0x0c203ac0,0x6d18139f,0x6422c144,0x2005d80d,
0x2006d82d,0x0095e000,0xd8ed0809,0x3fa22004,
0x2004dced,0x2002d88d,0xe000040b,0x0c060098,
0x2004d8ed,0xdced3fa3,0xe0002004,0xc1040086,
0x3ac16422,0x13900c06,0xc1446d18,0x37006421,
0x4ff0751d,0x691c6dde,0x0c043c40,0xc1643401,
0x138a6423,0xc1446d18,0xc0006423,0xd86d4c20,
0x2b002006,0x2006dc6d,0x2000d8cd,0x6d18129c,
0x6423c144,0x4c20c000,0xd8cd3700,0xd84d2000,
0x3ac02001,0xd80d0c1c,0xd82d2005,0xe0002006,
0x08090050,0x2004d8ed,0xdced3fa2,0xd88d2004,
0x040b2002,0x0053e000,0xd8ed0c06,0x3fa32004,
0x2004dced,0x0041e000,0x6422c104,0x0c293ac1,
0x4c827518,0x31002400,0x3edc6c46,0x70510c02,
0x6c467050,0x6022c101,0xd80d6884,0xd82d2007,
0xe0002008,0xd88d003a,0x2c002003,0x2003dc8d,
0x08073c40,0x2004d8ed,0xdced3fa0,0x04092004,
0x0035e000,0xd8ed0c06,0x3fa12004,0x2004dced,
0x4ff0751d,0x691c6dde,0x0c043c40,0xc1643401,
0x11976423,0xc1446d18,0xc0006423,0x75014c20,
0x65527545,0x4898783c,0x49b06900,0x44826114,
0x20009480,0x100adc0d,0x5981783c,0x48b07511,
0x65147554,0x4898783c,0x49b06904,0x44826114,
0x2100b440,0x1010dc2d,0x5981783c,0x48b07511,
0x65157554,0x3000783c,0x32003100,0x34003300,
0x36003500,0x105f3700,0x6421c002,0x6022c000,
0x3aa83aa6,0x6420c002,0x334010db,0x35005e8d,
0xb4a02403,0x0bfd6518,0x101910f8,0x6c037800,
0x6c036c03,0x6c036c03,0x64c21076,0xc0000c07,
0xc0016021,0x1010642b,0xc001b020,0x100e642b,
0x07fcb020,0xa0005081,0xe0201001,0xa0001000,
0x80004003,0x8000c001,0x8000d801,0xa000d801,
0x80008003,0x80000001,0x80001001,0xa0001001,
0x00000000,0x6000fff8,0x00000f58,0x00000fb4,
0x1324ffbb,0x6c036c03,0x6c036c03,0x6c036c03,
0x6c036c03,0x00000000,0x00000000,0x00000000
};
//i2c function
#define SPU_I2C_FUNC_WORDS 228
#define SPU_I2C_FUNC_BYTES SPU_I2C_FUNC_WORDS*4
const static int32_t SPU_I2C_FUNC_INDEX[16]={
0x00000000,0x0000004c,0x00000072,0x00000082,
0x0000010c,0x00000192,0x00000194,0x000001b0,
0x000001d4,0x00000206,0x0000022e,0x00000246,
0x00000000,0x00000000,0x00000000,0x00000286,
};
const static int32_t SPU_I2C_FUNC[228] = {
0x0004d80d,0x38c03413,0xc1440c0d,0xc1206421,
0x3cbe6024,0x6420c124,0x2004d80d,0x2005d82d,
0x38c1044c,0xc1440c09,0xc1206421,0x3cbe6024,
0x6420c124,0x34000464,0x6420c104,0x38c20280,
0x3caa0c02,0x6420c144,0x4c20c000,0xc1443413,
0xd80d6421,0xd82d2004,0xe0002005,0xc104011e,
0x02886420,0x2000d8ad,0xc1446d14,0xc0006420,
0x028b4c20,0x2000d8ad,0xc1446d14,0xc0006420,
0xc1004c20,0x3cdf6024,0x34020c05,0x1006dc8d,
0xd84d0482,0x3ac50004,0xd80d08cb,0xd82d2004,
0xe0002005,0x080900f6,0x08293ac3,0x08933ac4,
0xdc8d3408,0x046f1006,0x00efe000,0x6420c104,
0x0004d8ad,0x0c043cc0,0xdcad3da5,0x03830004,
0x2000d8ad,0xc1446d14,0xe0006420,0x0cfc00e8,
0xdc8d3401,0xd8ad1006,0x6d561007,0x3c406914,
0x34010cf3,0x6420c164,0x4c20c000,0xd8ad038d,
0x6d142000,0x6420c144,0x4c20c000,0x2006d80d,
0x2007d82d,0x6022c100,0x00cfe000,0x2002d88d,
0xdc8d2c00,0x3c402002,0x34000c1b,0x6420c104,
0xd8ad0399,0x6d142000,0x6420c144,0x00c7e000,
0x34040ccb,0x1006dc8d,0x1007d8ad,0x69146d56,
0x0cc23c40,0xc1643401,0xc0006420,0x139c4c20,
0x2000d8ad,0xd80d6d14,0x38c40004,0x35000c09,
0x6420c105,0xc1443ca8,0xc0006420,0x350f4c20,
0x6420c105,0x6420c144,0xdc8d3408,0xc0001006,
0x07b54c20,0xc10434fe,0x138e6421,0x6421c144,
0xc10535fc,0x3cac6420,0x6420c144,0x4c20c000,
0x2003d88d,0x6d564cb0,0x69147511,0x0c043c40,
0xc1643401,0x340e6420,0x6420c144,0x6421c144,
0x4c20c000,0x6024c120,0xc1243c9e,0x340e6420,
0x6420c144,0xc1443402,0x34106421,0x1006dc8d,
0x1007d8ad,0x69146d56,0x0c6e3c40,0xc1643401,
0xc0006420,0x34134c20,0x6421c144,0x2004d80d,
0x2005d82d,0x0041e000,0xc1043cb7,0x128e6420,
0x2000d8ad,0xc1446d14,0xc0006420,0x34024c20,
0x6421c144,0x3cbf34ff,0x6420c104,0xc1441287,
0xc0006420,0xd80d4c20,0x38852001,0x0c0c38c2,
0x6024c120,0x44974c97,0x6d1448a8,0x6420c124,
0x6421c124,0xdc0d3882,0x34ff2001,0x6421c104,
0xc144119b,0x35016421,0x6420c105,0xc1443cac,
0xc0006420,0x34204c20,0x1006dc8d,0x75010792,
0x65527545,0x4898783c,0x49b06900,0x44826114,
0x20009480,0x1008dc0d,0x5981783c,0x48b07511,
0x65147554,0x4898783c,0x49b06904,0x44826114,
0x2100b440,0x100edc2d,0x5981783c,0x48b07511,
0x65157554,0xc000783c,0x30004c20,0x32003100,
0x34003300,0x36003500,0x105e3700,0x6421c002,
0x6022c000,0x3aa83aa6,0x6420c002,0x334010da,
0x35005e8d,0xb4a02403,0x0bfd6518,0x101810f7,
0x6c037800,0x6c036c03,0x6c036c03,0x64c21075,
0xc0000c07,0xc0016021,0x100f642b,0xc001b020,
0x100d642b,0x07fcb020,0xc0003003,0x901fb89f,
0x80009901,0x9000999d,0x801fba03,0x801fba83,
0xc000030b,0x901fbca3,0xc0001507,0xc0000007,
0x00000000,0x6000fff8,0x0000046c,0x000004c4,
0x1324ffbb,0x6c036c03,0x6c036c03,0x6c036c03,
0x6c036c03,0x00000000,0x00000000,0x00000000
};
//can function
#define SPU_CAN_FUNC_WORDS 0
#define SPU_CAN_FUNC_BYTES SPU_CAN_FUNC_WORDS*4
const static int32_t SPU_CAN_FUNC_INDEX[16]={0};
const static int32_t SPU_CAN_FUNC[1] = {0};
//------------------------------------------
// ISR
//------------------------------------------
extern void ck_spu_usart_irqhandler(int32_t idx,spu_dev_signal_e signal);
extern void ck_spu_spi_irqhandler(int32_t idx,spu_dev_signal_e signal);
extern void ck_spu_i2c_irqhandler(int32_t idx,spu_dev_signal_e signal);
extern void ck_spu_can_irqhandler(int32_t idx,spu_dev_signal_e signal);
void ck_spu_irqhandler(int32_t idx)
{
ck_spu_priv_t *priv = &spu_instance[idx];
//ISR of particular device
int32_t base;
int32_t data;
int32_t intr_src;
int32_t i;
base = priv->base + GLOBAL_BASE;
getData(data,base,OFFSET_PGPIO_INTR_STATUS);
spu_pgpio_info_t pgpio_info;
for(i=0; i<32; i++){
intr_src = data & (1 << i);
if(intr_src!=0){
pgpio_info = get_pgpio_info(idx, i);
switch(pgpio_info.dev_type){
case ENUM_SPU_DEV_USART: ck_spu_usart_irqhandler(pgpio_info.dev_idx,pgpio_info.dev_signal); break;
case ENUM_SPU_DEV_SPI: ck_spu_spi_irqhandler(pgpio_info.dev_idx,pgpio_info.dev_signal); break;
case ENUM_SPU_DEV_I2C: ck_spu_i2c_irqhandler(pgpio_info.dev_idx,pgpio_info.dev_signal); break;
//case ENUM_SPU_DEV_CAN: ck_spu_can_irqhandler(pgpio_info.dev_idx,pgpio_info.dev_signal); break;
default: break;
}
}
}
}
//------------------------------------------
// CSI_DRIVER
//------------------------------------------
extern void csi_vic_enable_irq(int32_t irq_num);
extern void csi_vic_disable_irq(int32_t irq_num);
extern int32_t target_spu_init(int32_t pgpio[],uint32_t *base, uint32_t *irq);
spu_capabilities_t csi_spu_get_capabilities(spu_handle_t handle)
{
return spu_capabilities;
}
spu_handle_t csi_spu_initialize(int32_t pgpio[])
{
//get base address & irq
int32_t idx;
uint32_t base = 0u;
uint32_t irq;
ck_spu_priv_t *priv;
idx = target_spu_init(pgpio, &base, &irq);
if (idx<0){
return NULL;
}
priv = &spu_instance[idx];
priv->base = base;
priv->irq = irq;
csi_vic_enable_irq(priv->irq);
//initialize variable
priv->clk_en_vec = 0;
priv->clk_en = false;
priv->prog_used = 0;
return priv;
}
int32_t csi_spu_config(spu_handle_t handle,spu_capabilities_t capabilities)
{
ck_spu_priv_t *priv = handle;
//check if INST_RAM size enough or not
uint32_t func_index_base = 256u;
uint32_t inst_len = 0u;
if(capabilities.spu_usart==1){
priv->usart_func_index_base = func_index_base;
func_index_base+=64;
inst_len+=(SPU_USART_FUNC_BYTES);
}
if(capabilities.spu_spi==1){
priv->spi_func_index_base = func_index_base;
func_index_base+=512;
inst_len+=(SPU_SPI_FUNC_BYTES);
}
if(capabilities.spu_i2c==1){
priv->i2c_func_index_base = func_index_base;
func_index_base+=64;
inst_len+=(SPU_I2C_FUNC_BYTES);
}
if(capabilities.spu_can==1){
priv->can_func_index_base = func_index_base;
func_index_base+=64;
inst_len+=(SPU_CAN_FUNC_BYTES);
}
inst_len += func_index_base;
if((inst_len)>SPU_INST_RAM_SIZE){
return ERR_SPU(EDRV_SPU_INST_OVERFLOW);
}
//write INST_RAM
int i;
uint32_t func_base;
uint32_t glb_func_index_base;
uint32_t glb_func_base;
uint32_t data;
uint32_t offset;
func_base = func_index_base;
glb_func_index_base = 256 + (priv->base+INST_BASE);
glb_func_base = func_index_base + (priv->base+INST_BASE);
putData(0x1,priv->base+GLOBAL_BASE,OFFSET_BLOCKS_CLK_EN); //open BLOCKS-CLOCK
for(i=0;i<256;i+=4){
putData(0x0,priv->base+INST_BASE,i);
}
if(capabilities.spu_usart==1){
for(i=0;i<16;i++){
data=SPU_USART_FUNC_INDEX[i]+func_base;
offset = i<<2;
putData(data,glb_func_index_base,offset);
}
glb_func_index_base+=64;
for(i=0;i<SPU_USART_FUNC_WORDS;i++){
offset = i<<2;
putData(SPU_USART_FUNC[i],glb_func_base,offset);
}
func_base+=(SPU_USART_FUNC_BYTES);
glb_func_base+=(SPU_USART_FUNC_BYTES);
}
if(capabilities.spu_spi==1){
for(i=0;i<128;i++){
data=SPU_SPI_FUNC_INDEX[i]+func_base;
offset = i<<2;
putData(data,glb_func_index_base,offset);
}
glb_func_index_base+=512;
for(i=0;i<SPU_SPI_FUNC_WORDS;i++){
offset = i<<2;
putData(SPU_SPI_FUNC[i],glb_func_base,offset);
}
func_base+=(SPU_SPI_FUNC_BYTES);
glb_func_base+=(SPU_SPI_FUNC_BYTES);
}
if(capabilities.spu_i2c==1){
for(i=0;i<16;i++){
data=SPU_I2C_FUNC_INDEX[i]+func_base;
offset = i<<2;
putData(data,glb_func_index_base,offset);
}
glb_func_index_base+=64;
for(i=0;i<SPU_I2C_FUNC_WORDS;i++){
offset = i<<2;
putData(SPU_I2C_FUNC[i],glb_func_base,offset);
}
func_base+=(SPU_I2C_FUNC_BYTES);
glb_func_base+=(SPU_I2C_FUNC_BYTES);
}
if(capabilities.spu_can==1){
for(i=0;i<16;i++){
data=SPU_CAN_FUNC_INDEX[i]+func_base;
offset = i<<2;
putData(data,glb_func_index_base,offset);
}
glb_func_index_base+=64;
for(i=0;i<SPU_CAN_FUNC_WORDS;i++){
offset = i<<2;
putData(SPU_CAN_FUNC[i],glb_func_base,offset);
}
func_base+=(SPU_CAN_FUNC_BYTES);
glb_func_base+=(SPU_CAN_FUNC_BYTES);
}
putData(0x0,priv->base+GLOBAL_BASE,OFFSET_BLOCKS_CLK_EN); //close BLOCKS-CLOCK
return 0;
}
int32_t csi_spu_uninitialize(spu_handle_t handle)
{
ck_spu_priv_t *priv = handle;
csi_vic_disable_irq(priv->irq); //close interrupt
putData(0x0,priv->base+GLOBAL_BASE,OFFSET_BLOCKS_CLK_EN); //close BLOCKS-CLOCK
putData(0x0,priv->base+GLOBAL_BASE,OFFSET_PGPIO_CLK_EN); //close CLOCK
return 0;
}
//------------------------------------------
// function for device
//------------------------------------------
uint32_t spu_get_base(int32_t idx){
ck_spu_priv_t *priv = &spu_instance[idx];
return priv->base;
}
void spu_enable_clock(int32_t idx,int32_t pgpio)
{
ck_spu_priv_t *priv = &spu_instance[idx];
priv->clk_en_vec |= (1 << pgpio);
if(!priv->clk_en){
priv->clk_en = true;
putData(0x1,priv->base+GLOBAL_BASE,OFFSET_BLOCKS_CLK_EN);
}
}
void spu_disable_clock(int32_t idx,int32_t pgpio)
{
ck_spu_priv_t *priv = &spu_instance[idx];
priv->clk_en_vec &= ~(1 << pgpio);
if((priv->clk_en_vec==0) && priv->clk_en){
priv->clk_en = false;
putData(0x0,priv->base+GLOBAL_BASE,OFFSET_BLOCKS_CLK_EN);
}
}
int32_t spu_apply_prog(int32_t idx,int32_t bytes)
{
ck_spu_priv_t *priv = &spu_instance[idx];
int32_t tmp;
tmp = priv->prog_used;
priv->prog_used += bytes;
if(priv->prog_used > (SPU_PROG_RAM_SIZE)){
priv->prog_used = tmp;
return -1;
}
return tmp;
}
int32_t spu_get_usart_func_index_base(int32_t idx)
{
ck_spu_priv_t *priv = &spu_instance[idx];
return priv->usart_func_index_base;
}
int32_t spu_get_spi_func_index_base(int32_t idx)
{
ck_spu_priv_t *priv = &spu_instance[idx];
return priv->spi_func_index_base;
}
int32_t spu_get_i2c_func_index_base(int32_t idx)
{
ck_spu_priv_t *priv = &spu_instance[idx];
return priv->i2c_func_index_base;
}
int32_t spu_get_can_func_index_base(int32_t idx)
{
ck_spu_priv_t *priv = &spu_instance[idx];
return priv->can_func_index_base;
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,928 @@
/* ---------------------------------------------------------------------------
* Copyright (C) 2016 CSKY Limited. All rights reserved.
*
* Redistribution and use of this software 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 CSKY Ltd. nor the names of CSKY's contributors may
* be used to endorse or promote products derived from this software without
* specific prior written permission of CSKY Ltd.
*
* 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 THE COPYRIGHT OWNER OR CONTRIBUTORS
* 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.
* -------------------------------------------------------------------------- */
/******************************************************************************
* @file
* @brief
* @version V1.0
* @date
******************************************************************************/
#include <csi_config.h>
#include <stdint.h>
#include <stdbool.h>
#include <stddef.h>
#include "csi_core.h"
#include "drv_spi.h"
#include "ck_spu.h"
#include "ck_spu_spi.h"
#include "soc.h"
#include "pin_name.h"
#include "spu_pin_planning.h"
#include "stdio.h"
#include <string.h>
extern uint32_t spu_get_base(int32_t idx);
extern void spu_enable_clock(int32_t idx,int32_t pgpio);
extern void spu_disable_clock(int32_t idx,int32_t pgpio);
extern int32_t spu_apply_prog(int32_t idx,int32_t bytes);
extern int32_t spu_get_spi_func_index_base(int32_t idx);
extern int32_t get_spi_info(int32_t idx, int32_t *spu_idx,
int32_t *pgpio_sclk, int32_t *pgpio_mosi, int32_t *pgpio_miso, int32_t *pgpio_ssel);
//-------------------------------------------------
// data structure
//-------------------------------------------------
typedef struct{
//Hardware configuration
uint32_t spu_base;
uint32_t global_base;
uint32_t pgpio_base;
uint32_t prog_base;
uint32_t inst_base;
uint8_t spu_idx;
uint8_t pgpio_sclk;
uint8_t pgpio_ssel;
uint8_t pgpio_mosi;
uint8_t pgpio_miso;
//ssel pin
int32_t pin_ssel;
//call back
spi_event_cb_t cb_event;
//spi mode
spi_mode_e mode;
spi_format_e format;
spi_bit_order_e order;
spi_ss_mode_e ss_mode;
int32_t bit_width;
uint32_t default_value;
//variable
volatile spi_status_t status;
uint8_t block_mode;
void *tx_data_buf;
uint32_t tx_total_num;
volatile uint32_t tx_cur_num;
void *rx_data_buf;
uint32_t rx_total_num;
volatile uint32_t rx_cur_num;
} ck_spu_spi_priv_t;
static ck_spu_spi_priv_t spi_instance[CONFIG_SPI_NUM];
static const spi_capabilities_t spi_capabilities = {
1, /* Simplex Mode (Master and Slave) */
0, /* TI Synchronous Serial Interface */
0, /* Microwire Interface */
0 /* Signal Mode Fault event: \ref CSKY_SPI_EVENT_MODE_FAULT */
};
//-------------------------------------------------
// function
//-------------------------------------------------
static void enable_pgpio(spi_handle_t handle)
{
ck_spu_spi_priv_t *priv = handle;
uint32_t data;
getData(data,priv->global_base,OFFSET_PGPIO_CLK_EN);
data |= (1 << priv->pgpio_sclk);
data |= (1 << priv->pgpio_ssel);
data |= (1 << priv->pgpio_mosi);
data |= (1 << priv->pgpio_miso);
putData(data,priv->global_base,OFFSET_PGPIO_CLK_EN);
}
static void disable_pgpio(spi_handle_t handle)
{
ck_spu_spi_priv_t *priv = handle;
uint32_t data;
getData(data,priv->global_base,OFFSET_PGPIO_CLK_EN);
data &= ~(1 << priv->pgpio_sclk);
data &= ~(1 << priv->pgpio_ssel);
data &= ~(1 << priv->pgpio_mosi);
data &= ~(1 << priv->pgpio_miso);
putData(data,priv->global_base,OFFSET_PGPIO_CLK_EN);
}
static uint32_t get_clock_div(uint32_t sysclk,uint32_t baud)
{
return (sysclk / (baud << 1));
}
static void write_tx_fifo(spi_handle_t handle, uint32_t value)
{
ck_spu_spi_priv_t *priv = handle;
uint32_t fifo_head_w0;
uint32_t fifo_head_w1;
uint32_t fifo_depth;
uint32_t wr_offset;
uint32_t mem_addr;
uint32_t wr_pointer;
uint32_t wr_data;
//write fifo
getData(fifo_head_w0,priv->prog_base,SPI_OFFSET_TX_HEAD_W0);
getData(fifo_head_w1,priv->prog_base,SPI_OFFSET_TX_HEAD_W1);
fifo_depth = fifo_head_w0 >> 24;
wr_offset = fifo_head_w1 & fifo_depth;
mem_addr = fifo_head_w1 >> 16;
wr_pointer = ((mem_addr + wr_offset)<< 2) + priv->spu_base;
if(priv->order==SPI_ORDER_MSB2LSB){
wr_data = value << (32 - priv->bit_width);
}
else{
wr_data = value;
}
putData(wr_data,wr_pointer,0);
//increase fifo pointer
uint32_t head_hf_h;
uint32_t head_hf_l;
head_hf_h = fifo_head_w1 & 0xFFFF0000;
fifo_head_w1++;
head_hf_l = fifo_head_w1 & 0xFFFF;
fifo_head_w1 = head_hf_h | head_hf_l;
putData(fifo_head_w1,priv->prog_base,SPI_OFFSET_TX_HEAD_W1);
}
static void send_data(spi_handle_t handle)
{
ck_spu_spi_priv_t *priv = handle;
uint32_t fifo_head_w0;
uint32_t fifo_head_w1;
uint32_t head_sub;
uint32_t fifo_depth;
uint32_t mask;
uint32_t valid_entries;
//check tx_fifo valid entry
getData(fifo_head_w0,priv->prog_base,SPI_OFFSET_TX_HEAD_W0);
getData(fifo_head_w1,priv->prog_base,SPI_OFFSET_TX_HEAD_W1);
head_sub = fifo_head_w1 - fifo_head_w0;
fifo_depth = fifo_head_w0 >> 24;
mask = (fifo_depth + 1) | fifo_depth;
valid_entries = (fifo_depth + 1) - (head_sub & mask);
valid_entries--; //PE's requirement
//send data
uint32_t bytes_to_send;
uint32_t trans_len;
uint32_t intr;
uint32_t trans_data;
bytes_to_send = priv->tx_total_num - priv->tx_cur_num;
if(bytes_to_send <= valid_entries){
trans_len = bytes_to_send;
//close interrupt
getData(intr,priv->prog_base,SPI_OFFSET_INT);
intr |= (SPI_INT_TX_EMPTY << 16);
putData(intr,priv->prog_base,SPI_OFFSET_INT);
}
else{
trans_len = valid_entries;
}
priv->tx_cur_num += trans_len;
if(priv->bit_width>8){
while(trans_len>0){
trans_data = *(volatile uint16_t*)(priv->tx_data_buf);
write_tx_fifo(priv,trans_data);
priv->tx_data_buf = (uint16_t*)(priv->tx_data_buf) + 1;
trans_len--;
}
}
else{
while(trans_len>0){
trans_data = *(volatile uint8_t*)(priv->tx_data_buf);
write_tx_fifo(priv,trans_data);
priv->tx_data_buf = (uint8_t*)(priv->tx_data_buf) + 1;
trans_len--;
}
}
}
static uint32_t read_rx_fifo(spi_handle_t handle)
{
ck_spu_spi_priv_t *priv = handle;
uint32_t fifo_head_w0;
uint32_t fifo_head_w1;
uint32_t fifo_depth;
uint32_t rd_offset;
uint32_t mem_addr;
uint32_t rd_pointer;
uint32_t rd_data;
//read fifo
getData(fifo_head_w0,priv->prog_base,SPI_OFFSET_RX_HEAD_W0);
getData(fifo_head_w1,priv->prog_base,SPI_OFFSET_RX_HEAD_W1);
fifo_depth = fifo_head_w0 >> 24;
rd_offset = fifo_head_w0 & fifo_depth;
mem_addr = fifo_head_w1 >> 16;
rd_pointer = ((mem_addr + rd_offset) << 2) + priv->spu_base;
getData(rd_data,rd_pointer,0);
if(priv->order==SPI_ORDER_LSB2MSB){
rd_data = rd_data >> (32 - priv->bit_width);
}
else{
rd_data = rd_data & (0xFFFFFFFF >> (32 - priv->bit_width));
}
//increase fifo pointer
uint32_t head_hf_h;
uint32_t head_hf_l;
head_hf_h = fifo_head_w0 & 0xFFFF0000;
fifo_head_w0++;
head_hf_l = fifo_head_w0 & 0xFFFF;
fifo_head_w0 = head_hf_h | head_hf_l;
putData(fifo_head_w0,priv->prog_base,SPI_OFFSET_RX_HEAD_W0);
return rd_data;
}
static void receive_data(spi_handle_t handle)
{
ck_spu_spi_priv_t *priv = handle;
uint32_t fifo_head_w0;
uint32_t fifo_head_w1;
uint32_t head_sub;
uint32_t fifo_depth;
uint32_t mask;
uint32_t valid_entries;
//check rx_fifo valid entry
getData(fifo_head_w0,priv->prog_base,SPI_OFFSET_RX_HEAD_W0);
getData(fifo_head_w1,priv->prog_base,SPI_OFFSET_RX_HEAD_W1);
head_sub = fifo_head_w1 - fifo_head_w0;
fifo_depth = fifo_head_w0 >> 24;
mask = (fifo_depth + 1) | fifo_depth;
valid_entries = head_sub & mask;
//receive data
uint32_t trans_data;
priv->rx_cur_num += valid_entries;
if(priv->bit_width>8){
while(valid_entries > 0){
trans_data = read_rx_fifo(priv);
*((volatile uint16_t *)(priv->rx_data_buf)) = (uint16_t)trans_data;
priv->rx_data_buf = (uint16_t*)(priv->rx_data_buf) + 1;
valid_entries--;
}
}
else{
while(valid_entries > 0){
trans_data = read_rx_fifo(priv);
*((volatile uint8_t *)(priv->rx_data_buf)) = (uint8_t)trans_data;
priv->rx_data_buf = (uint8_t*)(priv->rx_data_buf) + 1;
valid_entries--;
}
}
}
static void get_status(spi_handle_t handle){
ck_spu_spi_priv_t *priv = handle;
uint32_t int_status;
getData(int_status,priv->prog_base,SPI_OFFSET_INT);
//deal with interrupt
if(((int_status & SPI_INT_TX_DONE)!=0) || ((int_status & SPI_INT_RX_DONE)!=0)){
priv->status.busy = 0U;
int_status &= 0xFFFF0000;
putData(int_status,priv->prog_base,SPI_OFFSET_INT);
}
}
/*
*/
//-------------------------------------------------
// IRQ
//-------------------------------------------------
void ck_spu_spi_irqhandler(int32_t idx,spu_dev_signal_e signal)
{
ck_spu_spi_priv_t *priv = &spi_instance[idx];
//get interrupt status
uint32_t int_status;
getData(int_status,priv->prog_base,SPI_OFFSET_INT);
//deal with interrupt
if((int_status & SPI_INT_TX_EMPTY)!=0){
send_data(priv);
}else if((int_status & SPI_INT_RX_FULL)!=0){
receive_data(priv);
}
if(((int_status & SPI_INT_TX_DONE)!=0) && ((int_status & SPI_INT_RX_DONE)!=0)){
receive_data(priv);
priv->status.busy = 0U;
if(priv->cb_event){
priv->cb_event(SPI_EVENT_TRANSFER_COMPLETE, idx);
}
}
else if((int_status & SPI_INT_TX_DONE)!=0){
priv->status.busy = 0U;
if(priv->cb_event){
priv->cb_event(SPI_EVENT_TX_COMPLETE, idx);
}
}
else if((int_status & SPI_INT_RX_DONE)!=0){
receive_data(priv);
priv->status.busy = 0U;
if(priv->cb_event){
priv->cb_event(SPI_EVENT_RX_COMPLETE, idx);
}
}
int_status &= 0xFFFF0000;
putData(int_status,priv->prog_base,SPI_OFFSET_INT);
}
//-------------------------------------------------
// API
//-------------------------------------------------
/**
\brief Get driver capabilities.
\param[in] idx spi index
\return \ref spi_capabilities_t
*/
spi_capabilities_t csi_spi_get_capabilities(int32_t idx)
{
if (idx < 0 || idx >= CONFIG_SPI_NUM) {
spi_capabilities_t ret;
memset(&ret, 0, sizeof(spi_capabilities_t));
return ret;
}
return spi_capabilities;
}
/**
\brief Initialize SPI Interface. 1. Initializes the resources needed for the SPI interface 2.registers event callback function
\param[in] idx spi index
\param[in] cb_event event call back function \ref spi_event_cb_t
\return return spi handle if success
*/
spi_handle_t csi_spi_initialize(int32_t idx, spi_event_cb_t cb_event)
{
//initialize instace
int32_t spu_idx;
int32_t pgpio_sclk;
int32_t pgpio_mosi;
int32_t pgpio_miso;
int32_t pgpio_ssel;
int32_t spi_idx;
ck_spu_spi_priv_t *priv;
int32_t apply_prog;
spi_idx = get_spi_info(idx,&spu_idx,&pgpio_sclk,&pgpio_mosi,&pgpio_miso,&pgpio_ssel);
if(spi_idx<0){
return NULL;
}
priv = &spi_instance[spi_idx];
priv->spu_base = spu_get_base(spu_idx);
priv->global_base = priv->spu_base + GLOBAL_BASE;
priv->pgpio_base = priv->spu_base + PGPIO_BASE;
priv->inst_base = priv->spu_base + INST_BASE;
priv->spu_idx = spu_idx;
priv->pgpio_sclk = pgpio_sclk;
priv->pgpio_ssel = pgpio_ssel;
priv->pgpio_mosi = pgpio_mosi;
priv->pgpio_miso = pgpio_miso;
apply_prog = spu_apply_prog(priv->spu_idx,SPI_PROG_BYTES);
if(apply_prog==-1){
return NULL;
}else{
priv->prog_base = priv->spu_base + PROG_BASE + apply_prog;
}
priv->pin_ssel = ssel;
//initialize SPI bus
uint32_t offset_pgpio;
enable_pgpio(priv);
offset_pgpio = (priv->pgpio_sclk << 4) + 8;
putData(0x0,priv->pgpio_base,offset_pgpio); //SCLK: CTRL
offset_pgpio = (priv->pgpio_ssel << 4) + 8;
putData(0xE,priv->pgpio_base,offset_pgpio); //SSEL: CTRL
offset_pgpio = (priv->pgpio_mosi << 4) + 8;
putData(0x0,priv->pgpio_base,offset_pgpio); //MOSI: CTRL
offset_pgpio = (priv->pgpio_miso << 4) + 8;
putData(0x0,priv->pgpio_base,offset_pgpio); //MISO: CTRL
//initialize INST_RAM
spu_enable_clock(priv->spu_idx,priv->pgpio_ssel);
//initialize variable
priv->default_value = 0;
priv->mode = SPI_MODE_INACTIVE;
priv->status.busy = 0U;
priv->status.data_lost = 0U;
priv->status.mode_fault = 0U;
//register callback function
priv->cb_event = cb_event;
return priv;
}
/**
\brief De-initialize SPI Interface. stops operation and releases the software resources used by the interface
\param[in] handle spi handle to operate.
\return 0 for success, negative for error code
*/
int32_t csi_spi_uninitialize(spi_handle_t handle)
{
ck_spu_spi_priv_t *priv = handle;
//initialize SPI bus
uint32_t offset_pgpio;
enable_pgpio(priv);
offset_pgpio = (priv->pgpio_sclk << 4) + 8;
putData(0x0,priv->pgpio_base,offset_pgpio); //SCLK: CTRL
offset_pgpio = (priv->pgpio_ssel << 4) + 8;
putData(0x0,priv->pgpio_base,offset_pgpio); //SSEL: CTRL
offset_pgpio = (priv->pgpio_mosi << 4) + 8;
putData(0x0,priv->pgpio_base,offset_pgpio); //MOSI: CTRL
offset_pgpio = (priv->pgpio_miso << 4) + 8;
putData(0x0,priv->pgpio_base,offset_pgpio); //MISO: CTRL
disable_pgpio(priv);
spu_disable_clock(priv->spu_idx,priv->pgpio_ssel);
//release data
priv->cb_event = NULL;
return 0;
}
/**
\brief config spi attributes.
\param[in] handle spi handle to operate.
\param[in] baud spi baud rate. if negative, then this attribute not changed
\param[in] mode spi mode \ref spi_mode_e. if negative, then this attribute not changed.
\param[in] speed spi speed \ref spi_speed_e.if negative, then this attribute not changed.
\param[in] addr_mode spi address mode \ref spi_address_mode_e. if negative, then this attribute not changed.
\param[in] slave_addr spi address of slave. if negative, then this attribute not changed.
\return 0 for success, negative for error code
*/
int32_t csi_spi_config(spi_handle_t handle,
int32_t baud,
spi_mode_e mode,
spi_format_e format,
spi_bit_order_e order,
spi_ss_mode_e ss_mode,
int32_t bit_width)
{
ck_spu_spi_priv_t *priv = handle;
//format
uint32_t func_index;
uint32_t offset_inst;
uint32_t data_inst;
uint32_t pgpio_ctrl_ssel = 0;
uint32_t pgpio_ctrl_sclk = 0;
bool sclk_ctrl_reconfig;
func_index = spu_get_spi_func_index_base(priv->spu_idx);
if(mode==SPI_MODE_MASTER_SIMPLEX || mode==SPI_MODE_MASTER){
switch(format){
case SPI_FORMAT_CPOL0_CPHA0:
pgpio_ctrl_sclk = 0x2;
break;
case SPI_FORMAT_CPOL1_CPHA0:
func_index += 64;
pgpio_ctrl_sclk = 0xE;
break;
case SPI_FORMAT_CPOL0_CPHA1:
func_index += 128;
pgpio_ctrl_sclk = 0x2;
break;
case SPI_FORMAT_CPOL1_CPHA1:
func_index += 192;
pgpio_ctrl_sclk = 0xE;
break;
}
sclk_ctrl_reconfig = true;
pgpio_ctrl_ssel = 0xE;
}
else{
switch(format){
case SPI_FORMAT_CPOL0_CPHA0:
func_index += 256;
break;
case SPI_FORMAT_CPOL1_CPHA0:
func_index += 320;
break;
case SPI_FORMAT_CPOL0_CPHA1:
func_index += 384;
break;
case SPI_FORMAT_CPOL1_CPHA1:
func_index += 448;
break;
}
if(priv->mode!=SPI_MODE_SLAVE_SIMPLEX && priv->mode!=SPI_MODE_SLAVE){
sclk_ctrl_reconfig = true;
pgpio_ctrl_ssel = 0x0;
pgpio_ctrl_sclk = 0x0;
}
else{
sclk_ctrl_reconfig = false;
}
}
offset_inst = priv->pgpio_ssel << 3;
data_inst = (func_index<<16) | (priv->prog_base - priv->spu_base);
putData(data_inst,priv->inst_base,offset_inst);
//mode
uint32_t context;
priv->mode = mode;
offset_inst = (priv->pgpio_ssel << 3) + 4;
if(mode==SPI_MODE_MASTER_SIMPLEX){
context = (priv->pgpio_sclk) | (priv->pgpio_mosi << 5) | (priv->pgpio_mosi << 10) | (priv->pgpio_ssel << 15);
putData(context,priv->inst_base,offset_inst);
}
else if(mode==SPI_MODE_SLAVE_SIMPLEX){
context = (priv->pgpio_sclk) | (priv->pgpio_miso << 5) | (priv->pgpio_miso << 10) | (priv->pgpio_ssel << 15);
putData(context,priv->inst_base,offset_inst);
}
else{
context = (priv->pgpio_sclk) | (priv->pgpio_mosi << 5) | (priv->pgpio_miso << 10) | (priv->pgpio_ssel << 15);
putData(context,priv->inst_base,offset_inst);
}
//ss_mode
uint32_t io_reuse_addr=0;
uint32_t io_reuse_data;
//HOBBIT_GIPO0_PORTCTL_REG
getData(io_reuse_data,CSKY_IOC_BASE, io_reuse_addr);
//printf("io_reuse_data0=%x\n",io_reuse_data);
if(ss_mode==SPI_SS_MASTER_HW_OUTPUT){
io_reuse_data |= 1<<priv->pin_ssel;
putData(io_reuse_data,CSKY_IOC_BASE, io_reuse_addr);
}else if(ss_mode==SPI_SS_MASTER_SW){
io_reuse_data &= ~(1<<priv->pin_ssel);
putData(io_reuse_data,CSKY_IOC_BASE, io_reuse_addr);
}
//HOBBIT_IOMUX0L_REG
io_reuse_addr += 8;
getData(io_reuse_data,CSKY_IOC_BASE, io_reuse_addr);
//printf("io_reuse_data1=%x\n",io_reuse_data);
if(ss_mode==SPI_SS_MASTER_HW_OUTPUT){
io_reuse_data |= 2<<(priv->pin_ssel*2);
putData(io_reuse_data,CSKY_IOC_BASE, io_reuse_addr);
}
//baud
uint32_t offset_pgpio;
uint32_t clk_div;
clk_div = (SPI_FILTER_COE) << 23;
if(mode==SPI_MODE_MASTER || mode==SPI_MODE_MASTER_SIMPLEX){
clk_div |= get_clock_div(LSP_DEFAULT_FREQ,baud);
}
else{
clk_div |= 1;
}
offset_pgpio = (priv->pgpio_sclk << 4) + 4;
putData(clk_div,priv->pgpio_base,offset_pgpio); //SCLK: CLK_DIV
if(sclk_ctrl_reconfig){
offset_pgpio+=4;
putData(pgpio_ctrl_sclk,priv->pgpio_base,offset_pgpio); //SCLK: CTRL
}
offset_pgpio = (priv->pgpio_ssel << 4) + 4;
putData(clk_div,priv->pgpio_base,offset_pgpio); //SSEL: CLK_DIV
offset_pgpio+=4;
putData(pgpio_ctrl_ssel,priv->pgpio_base,offset_pgpio); //SSEL: CTRL
offset_pgpio = (priv->pgpio_mosi << 4) + 4;
putData(clk_div,priv->pgpio_base,offset_pgpio); //MOSI: CLK_DIV
offset_pgpio = (priv->pgpio_miso << 4) + 4;
putData(clk_div,priv->pgpio_base,offset_pgpio); //MISO: CLK_DIV
//order
//bit_width
uint32_t refer_clk;
priv->order = order;
priv->bit_width = bit_width;
refer_clk = (priv->pgpio_sclk << 21);
refer_clk |= ((bit_width-1) << 2);
if(order==SPI_ORDER_MSB2LSB){refer_clk |= (1 << 28);}
putData(refer_clk, priv->prog_base, SPI_OFFSET_REFER_CLK);
//variable
priv->status.busy = 0U;
priv->status.data_lost = 0U;
priv->status.mode_fault = 0U;
return 0;
}
/**
\brief sending data to SPI transmitter,(received data is ignored).
if non-blocking mode, this function only start the sending,
\ref spi_event_e is signaled when operation completes or error happens.
\ref csi_spi_get_status can indicates operation status.
if blocking mode, this function return after operation completes or error happens.
\param[in] handle spi handle to operate.
\param[in] data Pointer to buffer with data to send to SPI transmitter. data_type is : uint8_t for 1..8 data bits, uint16_t for 9..16 data bits,uint32_t for 17..32 data bits,
\param[in] num Number of data items to send.
\return error code
*/
//int32_t csi_spi_send(spi_handle_t handle, const void *data, uint32_t num, uint8_t block_mode, bool back_to_back, bool cs_pend)
int32_t csi_spi_send(spi_handle_t handle, const void *data, uint32_t num)
{
ck_spu_spi_priv_t *priv = handle;
priv->tx_data_buf = (void *)data;
priv->tx_total_num = num;
priv->tx_cur_num = 0;
//config: ctrl
uint32_t ctrl=SPI_TMOD_TRANSMIT | SPI_BACK_TO_BACK;
// if(back_to_back){
// ctrl |= SPI_BACK_TO_BACK;
// }
// if(cs_pend){
// ctrl |= SPI_CS_PEND;
// }
putData(ctrl,priv->prog_base,SPI_OFFSET_CTRL);
//config: TRANS_LEN
putData(num,priv->prog_base,SPI_OFFSET_TRANS_LEN);
//config: INT
putData(0,priv->prog_base,SPI_OFFSET_INT);
//config: tx_fifo_head
uint32_t fifo_head;
fifo_head = (SPI_TX_FIFO_DEPTH << 24) | (SPI_TX_FIFO_EMPTY_TL << 16);
putData(fifo_head,priv->prog_base,SPI_OFFSET_TX_HEAD_W0);
fifo_head = (priv->prog_base - priv->spu_base + SPI_OFFSET_TX_MEM) << 14;
putData(fifo_head,priv->prog_base,SPI_OFFSET_TX_HEAD_W1);
//send data
priv->status.busy = 1U;
send_data(priv);
//start PE
uint32_t pgpio_decode;
pgpio_decode = (1 << priv->pgpio_ssel);
putData(pgpio_decode,priv->global_base,OFFSET_PGPIO_START_EN);
if(priv->block_mode){
do{
get_status(priv);
}while(priv->status.busy);
}
return 0;
}
/**
\brief Start receiving data as SPI Master.
This function is non-blocking,\ref spi_event_e is signaled when transfer completes or error happens.
drv_*_get_status can indicates transmission status.
\param[in] handle spi handle to operate.
\param[out] data Pointer to buffer for data to receive from SPI receiver
\param[in] num Number of data items to receive
\return 0 for success, negative for error code
*/
//int32_t csi_spi_receive(spi_handle_t handle, void *data, uint32_t num, uint8_t block_mode, bool back_to_back, bool cs_pend)
int32_t csi_spi_receive(spi_handle_t handle, void *data, uint32_t num)
{
ck_spu_spi_priv_t *priv = handle;
priv->rx_data_buf = data;
priv->rx_total_num = num;
priv->rx_cur_num = 0;
//config: ctrl
uint32_t ctrl=SPI_TMOD_RECEIVE | SPI_BACK_TO_BACK;
//if(back_to_back){
// ctrl |= SPI_BACK_TO_BACK;
//}
//if(cs_pend){
// ctrl |= SPI_CS_PEND;
//}
putData(ctrl,priv->prog_base,SPI_OFFSET_CTRL);
//putData(SPI_TMOD_RECEIVE,priv->prog_base,SPI_OFFSET_CTRL);
//config: TRANS_LEN
putData(num,priv->prog_base,SPI_OFFSET_TRANS_LEN);
//config: INT
putData(0,priv->prog_base,SPI_OFFSET_INT);
//config: rx_fifo_head
uint32_t fifo_head;
fifo_head = (SPI_RX_FIFO_DEPTH << 24) | (SPI_RX_FIFO_FULL_TL << 16);
putData(fifo_head,priv->prog_base,SPI_OFFSET_RX_HEAD_W0);
fifo_head = (priv->prog_base - priv->spu_base + SPI_OFFSET_RX_MEM) << 14;
putData(fifo_head,priv->prog_base,SPI_OFFSET_RX_HEAD_W1);
//start PE
uint32_t pgpio_decode;
priv->status.busy = 1U;
pgpio_decode = (1 << priv->pgpio_ssel);
putData(pgpio_decode,priv->global_base,OFFSET_PGPIO_START_EN);
if(priv->block_mode){
do{
get_status(priv);
}while(priv->status.busy);
}
return 0;
}
/**
\brief sending/receiving data to/from SPI transmitter/receiver.
if non-blocking mode, this function only start the transfer,
\ref spi_event_e is signaled when operation completes or error happens.
\ref csi_spi_get_status can indicates operation status.
if blocking mode, this function return after operation completes or error happens.
\param[in] handle spi handle to operate.
\param[in] data_out Pointer to buffer with data to send to SPI transmitter
\param[out] data_in Pointer to buffer for data to receive from SPI receiver
\param[in] num_out Number of data items to send
\param[in] num_in Number of data items to receive
\param[in] block_mode blocking and non_blocking to selcect
\return error code
*/
//int32_t csi_spi_transfer(spi_handle_t handle, const void *data_out, void *data_in, uint32_t num_out, uint32_t num_in, uint8_t block_mode, bool back_to_back, bool cs_pend)
int32_t csi_spi_transfer(spi_handle_t handle, const void *data_out, void *data_in, uint32_t num_out, uint32_t num_in)
{
ck_spu_spi_priv_t *priv = handle;
priv->tx_data_buf = (void *)data_out;
priv->tx_total_num = num_out;
priv->tx_cur_num = 0;
priv->rx_data_buf = data_in;
priv->rx_total_num = num_in;
priv->rx_cur_num = 0;
//config: ctrl
uint32_t ctrl=SPI_TMOD_TRANSFER | SPI_BACK_TO_BACK;
//if(back_to_back){
// ctrl |= SPI_BACK_TO_BACK;
//}
//if(cs_pend){
// ctrl |= SPI_CS_PEND;
//}
putData(ctrl,priv->prog_base,SPI_OFFSET_CTRL);
//putData(SPI_TMOD_TRANSFER,priv->prog_base,SPI_OFFSET_CTRL);
//config: TRANS_LEN
putData(num_in,priv->prog_base,SPI_OFFSET_TRANS_LEN);
//config: INT
putData(0x0,priv->prog_base,SPI_OFFSET_INT);
//config: tx_fifo_head & rx_fifo_head
uint32_t fifo_head;
fifo_head = (SPI_TX_FIFO_DEPTH << 24) | (SPI_TX_FIFO_EMPTY_TL << 16);
putData(fifo_head,priv->prog_base,SPI_OFFSET_TX_HEAD_W0);
fifo_head = (priv->prog_base - priv->spu_base + SPI_OFFSET_TX_MEM) << 14;
putData(fifo_head,priv->prog_base,SPI_OFFSET_TX_HEAD_W1);
fifo_head = (SPI_RX_FIFO_DEPTH << 24) | (SPI_RX_FIFO_FULL_TL << 16);
putData(fifo_head,priv->prog_base,SPI_OFFSET_RX_HEAD_W0);
fifo_head = (priv->prog_base - priv->spu_base + SPI_OFFSET_RX_MEM) << 14;
putData(fifo_head,priv->prog_base,SPI_OFFSET_RX_HEAD_W1);
//send data
send_data(priv);
priv->status.busy = 1U;
//start PE
uint32_t pgpio_decode;
pgpio_decode = (1 << priv->pgpio_ssel);
putData(pgpio_decode,priv->global_base,OFFSET_PGPIO_START_EN);
if(priv->block_mode){
do{
get_status(priv);
}while(priv->status.busy);
}
return 0;
}
int32_t csi_spi_abort_transfer(spi_handle_t handle){
return 0;
}
spi_status_t csi_spi_get_status(spi_handle_t handle){
ck_spu_spi_priv_t *priv = handle;
if(priv->block_mode){
get_status(priv);
}
return priv->status;
}
/**
\brief config the SPI block mode.
\param[in] handle spi handle
\param[in] flag 1 - enbale the block mode. 0 - disable the block mode
\return error code
*/
int32_t csi_spi_config_block_mode(spi_handle_t handle, int32_t flag)
{
dw_spi_priv_t *spi_priv = handle;
if (flag == 1) {
spi_priv->block_mode = 1;
} else if (flag == 0) {
spi_priv->block_mode = 0;
} else {
ERR_SPI(SPI_ERROR_MODE);
}
return 0;
}

View file

@ -0,0 +1,846 @@
/*
* Copyright (C) 2017 C-SKY Microsystems Co., Ltd. All rights reserved.
*
* 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 ck_spu_usart.c
* @brief CSI Source File for usart Driver
* @version V1.0
* @date 02. June 2017
******************************************************************************/
#include <csi_config.h>
#include <stdint.h>
#include <stdbool.h>
#include <stddef.h>
#include "csi_core.h"
#include "drv_usart.h"
#include "ck_spu_usart.h"
#include "ck_spu.h"
#include "soc.h"
#include "pin_name.h"
#include "spu_pin_planning.h"
#define ERR_USART(errno) (CSI_DRV_ERRNO_USART_BASE | errno)
extern uint32_t spu_get_base(int32_t idx);
extern void spu_enable_clock(int32_t idx,int32_t pgpio);
extern void spu_disable_clock(int32_t idx,int32_t pgpio);
extern int32_t spu_apply_prog(int32_t idx,int32_t bytes);
extern int32_t spu_get_usart_func_index_base(int32_t idx);
extern int32_t get_usart_info(int32_t int32_tx, int32_t pin_rx, int32_t *spu_idx, int32_t *pgpio_tx, int32_t *pgpio_rx);
//-------------------------------------------------
// Data Private
//-------------------------------------------------
typedef struct{
//hardware config
uint32_t spu_base;
uint32_t spu_irq;
uint32_t global_base;
uint32_t pgpio_base;
uint32_t prog_base_tx;
uint32_t prog_base_rx;
uint32_t inst_base;
uint8_t sin_id;
uint8_t sout_id;
uint32_t spu_idx;
//call back
usart_event_cb_t cb_event;
//mode
usart_mode_e mode;
usart_data_bits_e data_bits;
//variable
volatile bool tx_busy;
volatile bool rx_busy;
void *tx_data_buf;
uint32_t tx_total_num;
volatile uint32_t tx_cur_num;
void *rx_data_buf;
uint32_t rx_total_num;
volatile uint32_t rx_cur_num;
} ck_spu_usart_priv_t;
static ck_spu_usart_priv_t usart_instance[CONFIG_SPU_USART_NUM];
static const usart_capabilities_t usart_capabilities = {
.asynchronous = 1, /* supports USART (Asynchronous) mode */
.synchronous_master = 0, /* supports Synchronous Master mode */
.synchronous_slave = 0, /* supports Synchronous Slave mode */
.single_wire = 0, /* supports USART Single-wire mode */
.event_tx_complete = 1, /* Transmit completed event */
.event_rx_timeout = 0, /* Signal receive character timeout event */
};
//-------------------------------------------------
// function
//-------------------------------------------------
static void enable_pgpio(usart_handle_t handle)
{
ck_spu_usart_priv_t *priv = handle;
uint32_t data;
getData(data,priv->global_base,OFFSET_PGPIO_CLK_EN);
data |= (1 << priv->sout_id);
data |= (1 << priv->sin_id);
putData(data,priv->global_base,OFFSET_PGPIO_CLK_EN);
}
static void disable_pgpio(usart_handle_t handle)
{
ck_spu_usart_priv_t *priv = handle;
uint32_t data;
getData(data,priv->global_base,OFFSET_PGPIO_CLK_EN);
data &= ~(1 << priv->sout_id);
data &= ~(1 << priv->sin_id);
putData(data,priv->global_base,OFFSET_PGPIO_CLK_EN);
}
static uint32_t get_clock_div(uint32_t sysclk,uint32_t baud)
{
uint32_t clock_freq;
clock_freq = baud << 4;
return (sysclk / clock_freq);
}
static void write_tx_fifo(usart_handle_t handle, uint32_t value)
{
ck_spu_usart_priv_t *priv = handle;
uint32_t fifo_head_w0;
uint32_t fifo_head_w1;
uint32_t fifo_depth;
uint32_t wr_offset;
uint32_t mem_addr;
uint32_t wr_pointer;
//write fifo
getData(fifo_head_w0,priv->prog_base_tx,USART_OFFSET_FIFO_HEAD_W0);
getData(fifo_head_w1,priv->prog_base_tx,USART_OFFSET_FIFO_HEAD_W1);
fifo_depth = fifo_head_w0 >> 24;
wr_offset = fifo_head_w1 & fifo_depth;
mem_addr = fifo_head_w1 >> 16;
wr_pointer = ((mem_addr + wr_offset)<< 2) + priv->spu_base;
putData(value,wr_pointer,0);
//increase fifo pointer
uint32_t head_hf_h;
uint32_t head_hf_l;
head_hf_h = fifo_head_w1 & 0xFFFF0000;
fifo_head_w1++;
head_hf_l = fifo_head_w1 & 0xFFFF;
fifo_head_w1 = head_hf_h | head_hf_l;
putData(fifo_head_w1,priv->prog_base_tx,USART_OFFSET_FIFO_HEAD_W1);
}
static void send_data(usart_handle_t handle)
{
ck_spu_usart_priv_t *priv = handle;
uint32_t fifo_head_w0;
uint32_t fifo_head_w1;
uint32_t head_sub;
uint32_t fifo_depth;
uint32_t mask;
uint32_t valid_entries;
//check tx_fifo valid entry
getData(fifo_head_w0,priv->prog_base_tx,USART_OFFSET_FIFO_HEAD_W0);
getData(fifo_head_w1,priv->prog_base_tx,USART_OFFSET_FIFO_HEAD_W1);
head_sub = fifo_head_w1 - fifo_head_w0;
fifo_depth = fifo_head_w0 >> 24;
mask = (fifo_depth + 1) | fifo_depth;
valid_entries = (fifo_depth + 1) - (head_sub & mask);
//send data
uint32_t bytes_to_send;
uint32_t trans_len;
uint32_t intr;
uint32_t trans_data;
bytes_to_send = priv->tx_total_num - priv->tx_cur_num;
if(bytes_to_send <= valid_entries){
trans_len = bytes_to_send;
//close interrupt
getData(intr,priv->prog_base_tx,USART_OFFSET_INT);
intr |= (USART_INT_TX_EMPTY << 16);
putData(intr,priv->prog_base_tx,USART_OFFSET_INT);
}
else{
trans_len = valid_entries;
}
priv->tx_cur_num += trans_len;
uint32_t data_mask;
data_mask = (1<<(priv->data_bits+5))-1;
if(priv->data_bits>USART_DATA_BITS_8){
while(trans_len>0){
trans_data = *(volatile uint16_t*)(priv->tx_data_buf);
trans_data &= data_mask;
write_tx_fifo(priv,trans_data);
priv->tx_data_buf = (uint16_t*)(priv->tx_data_buf) + 1;
trans_len--;
}
}
else{
while(trans_len>0){
trans_data = *(volatile uint8_t*)(priv->tx_data_buf);
trans_data &= data_mask;
write_tx_fifo(priv,trans_data);
priv->tx_data_buf = (uint8_t*)(priv->tx_data_buf) + 1;
trans_len--;
}
}
/*
trans_data = *(priv->tx_data_buf);
trans_data &= data_mask;
write_tx_fifo(priv,trans_data);
priv->tx_data_buf++;
trans_len--;
*/
}
static uint32_t read_rx_fifo(usart_handle_t handle)
{
ck_spu_usart_priv_t *priv = handle;
uint32_t prog_base;
uint32_t fifo_head_w0;
uint32_t fifo_head_w1;
uint32_t fifo_depth;
uint32_t rd_offset;
uint32_t mem_addr;
uint32_t rd_pointer;
uint32_t rd_data;
if(priv->mode==USART_MODE_SINGLE_WIRE){
prog_base = priv->prog_base_tx;
}
else{
prog_base = priv->prog_base_rx;
}
//read fifo
getData(fifo_head_w0,prog_base,USART_OFFSET_FIFO_HEAD_W0);
getData(fifo_head_w1,prog_base,USART_OFFSET_FIFO_HEAD_W1);
fifo_depth = fifo_head_w0 >> 24;
rd_offset = fifo_head_w0 & fifo_depth;
mem_addr = fifo_head_w1 >> 16;
rd_pointer = ((mem_addr + rd_offset) << 2) + priv->spu_base;
getData(rd_data,rd_pointer,0);
//increase fifo pointer
uint32_t head_hf_h;
uint32_t head_hf_l;
head_hf_h = fifo_head_w0 & 0xFFFF0000;
fifo_head_w0++;
head_hf_l = fifo_head_w0 & 0xFFFF;
fifo_head_w0 = head_hf_h | head_hf_l;
putData(fifo_head_w0,prog_base,USART_OFFSET_FIFO_HEAD_W0);
return rd_data;
}
static void receive_data(usart_handle_t handle)
{
ck_spu_usart_priv_t *priv = handle;
uint32_t prog_base;
uint32_t fifo_head_w0;
uint32_t fifo_head_w1;
uint32_t head_sub;
uint32_t fifo_depth;
uint32_t mask;
uint32_t valid_entries;
if(priv->mode==USART_MODE_SINGLE_WIRE){
prog_base = priv->prog_base_tx;
}
else{
prog_base = priv->prog_base_rx;
}
//check rx_fifo valid entry
getData(fifo_head_w0,prog_base,USART_OFFSET_FIFO_HEAD_W0);
getData(fifo_head_w1,prog_base,USART_OFFSET_FIFO_HEAD_W1);
head_sub = fifo_head_w1 - fifo_head_w0;
fifo_depth = fifo_head_w0 >> 24;
mask = (fifo_depth + 1) | fifo_depth;
valid_entries = head_sub & mask;
//receive data
uint32_t trans_data;
priv->rx_cur_num += valid_entries;
if(priv->data_bits>USART_DATA_BITS_8){
while(valid_entries > 0){
trans_data = read_rx_fifo(priv);
*((volatile uint16_t *)(priv->rx_data_buf)) = (uint16_t)trans_data;
priv->rx_data_buf = (uint16_t*)(priv->rx_data_buf) + 1;
valid_entries--;
}
}
else{
while(valid_entries > 0){
trans_data = read_rx_fifo(priv);
*((volatile uint8_t *)(priv->rx_data_buf)) = (uint8_t)trans_data;
priv->rx_data_buf = (uint8_t*)(priv->rx_data_buf) + 1;
valid_entries--;
}
}
}
/**
\brief get character in query mode.
\param[in] instance usart instance to operate.
\param[in] the pointer to the recieve charater.
\return error code
*/
int32_t csi_usart_getchar(usart_handle_t handle, uint8_t *ch)
{
ck_spu_usart_priv_t *priv = handle;
while(priv->rx_busy);
csi_usart_receive(priv, ch, 1);
while(priv->rx_busy);
return 0;
}
/**
\brief transmit character in query mode.
\param[in] instance usart instance to operate.
\param[in] ch the input charater
\return error code
*/
int32_t csi_usart_putchar(usart_handle_t handle, uint8_t ch)
{
ck_spu_usart_priv_t *priv = handle;
char send_char;
while(priv->tx_busy);
if(ch=='\n'){
send_char='\r';
csi_usart_send(handle,&send_char,1);
while(priv->tx_busy);
}
send_char=ch;
csi_usart_send(handle,&send_char,1);
while(priv->tx_busy);
return 0;
}
//==============================================================
// ISR
//==============================================================
/**
\brief the interrupt service function.
\param[in] index of usart instance.
*/
void ck_spu_usart_irqhandler(int32_t idx,spu_dev_signal_e signal)
{
ck_spu_usart_priv_t *priv = &usart_instance[idx];
//get interrupt status
uint32_t prog_base;
uint32_t int_status;
if(signal==ENUM_USART_TX){
prog_base = priv->prog_base_tx;
}
else{
prog_base = priv->prog_base_rx;
}
getData(int_status,prog_base,USART_OFFSET_INT);
//deal with interrupt
if((int_status & USART_INT_TX_DONE)!=0){
priv->tx_busy = false;
if(priv->cb_event){
priv->cb_event(USART_EVENT_SEND_COMPLETE, idx);
}
}
else if((int_status & USART_INT_TX_EMPTY)!=0){
send_data(priv);
}
if((int_status & USART_INT_RX_DONE)!=0){
receive_data(priv);
priv->rx_busy = false;
if(priv->cb_event){
priv->cb_event(USART_EVENT_RECEIVE_COMPLETE, idx);
}
}
else if((int_status & USART_INT_RX_FULL)!=0){
receive_data(priv);
}
if((int_status & USART_INT_PARITY_ERR)!=0){
if(priv->cb_event){
priv->cb_event(USART_EVENT_RX_PARITY_ERROR, idx);
}
}
if((int_status & USART_INT_STOP_ERR)!=0){
if(priv->cb_event){
priv->cb_event(USART_EVENT_RX_FRAMING_ERROR,idx);
}
}
int_status &= 0xFFFF0000;
putData(int_status,prog_base,USART_OFFSET_INT);
}
//==============================================================
// DRIVER
//==============================================================
usart_capabilities_t csi_usart_get_capabilities(int32_t idx)
{
if (idx < 0 || idx >= CONFIG_USART_NUM) {
usart_capabilities_t ret;
memset(&ret, 0, sizeof(usart_capabilities_t));
return ret;
}
return usart_capabilities;
}
/**
\brief Initialize USART Interface. 1. Initializes the resources needed for the USART interface 2.registers event callback function
\param[in] usart pin of tx
\param[in] usart pin of rx
\param[in] cb_event Pointer to \ref usart_event_cb_t
\return return usart handle if success
*/
usart_handle_t csi_usart_initialize(int32_t idx, usart_event_cb_t cb_event
{
//initialize instace
int32_t spu_idx;
int32_t pgpio_tx;
int32_t pgpio_rx;
int32_t usart_idx;
ck_spu_usart_priv_t *priv;
int32_t apply_prog;
usart_idx = get_usart_info(idx, &spu_idx, &pgpio_tx, &pgpio_rx);
if(usart_idx<0){
return NULL;
}
priv = &usart_instance[usart_idx];
priv->spu_base = spu_get_base(spu_idx);
priv->global_base = priv->spu_base + GLOBAL_BASE;
priv->pgpio_base = priv->spu_base + PGPIO_BASE;
priv->inst_base = priv->spu_base + INST_BASE;
priv->spu_idx = spu_idx;
priv->sout_id = pgpio_tx;
priv->sin_id = pgpio_rx;
apply_prog = spu_apply_prog(priv->spu_idx,USART_PROG_BYTES);
if(apply_prog==-1){
return NULL;
}else{
priv->prog_base_tx = priv->spu_base + PROG_BASE + apply_prog;
priv->prog_base_rx = priv->prog_base_tx + USART_PROG_BYTES;
}
//initialize USART bus
uint32_t offset_pgpio;
enable_pgpio(priv);
offset_pgpio = (priv->sout_id << 4) + 8;
putData(0xE,priv->pgpio_base,offset_pgpio); //SDOUT: CTRL
if(priv->sout_id!=priv->sin_id){
offset_pgpio = (priv->sin_id << 4) + 8;
putData(0x0,priv->pgpio_base,offset_pgpio); //SIN: CTRL
}
//inst_ram: index
spu_enable_clock(priv->spu_idx,priv->sout_id);
uint32_t func_index_base;
uint32_t offset_inst;
uint32_t data_inst;
func_index_base = spu_get_usart_func_index_base(priv->spu_idx);
offset_inst = (priv->sout_id << 3);
data_inst = (func_index_base<<16) | (priv->prog_base_tx-priv->spu_base);
putData(data_inst,priv->inst_base,offset_inst);
offset_inst = (priv->sout_id << 3) + 4;
putData(priv->sout_id,priv->inst_base,offset_inst);
offset_inst = (priv->sin_id << 3);
data_inst = (func_index_base<<16) | (priv->prog_base_rx-priv->spu_base);
putData(data_inst,priv->inst_base,offset_inst);
offset_inst = (priv->sin_id << 3) + 4;
putData(priv->sin_id,priv->inst_base,offset_inst);
//variable
priv->tx_busy = false;
priv->rx_busy = false;
//register callback function
priv->cb_event = cb_event;
return priv;
}
/**
\brief De-initialize UART Interface. stops operation and releases the software resources used by the interface
\param[in] handle usart handle to operate.
\return error code
*/
int32_t csi_usart_uninitialize(usart_handle_t handle)
{
ck_spu_usart_priv_t *priv = handle;
disable_pgpio(priv);
spu_disable_clock(priv->spu_idx,priv->sout_id);
priv->cb_event = NULL;
return 0;
}
/**
\brief config usart mode.
\param[in] handle usart handle to operate.
\param[in] mode \ref usart_mode_e
\param[in] parity \ref usart_parity_e
\param[in] stopbits \ref usart_stop_bits_e
\param[in] bits \ref usart_data_bits_e
\param[in] baud configured baud
\return error code
*/
int32_t csi_usart_config(usart_handle_t handle,
uint32_t baud,
usart_mode_e mode,
usart_parity_e parity,
usart_stop_bits_e stopbits,
usart_data_bits_e bits)
{
ck_spu_usart_priv_t *priv = handle;
//mode
priv->mode = mode;
//baud
uint32_t offset_pgpio;
uint32_t clk_div;
offset_pgpio = (priv->sout_id << 4) + 4;
clk_div = get_clock_div(baud);
clk_div |= (USART_FILTER_COE << 23);
putData(clk_div,priv->pgpio_base,offset_pgpio);
if(mode==USART_MODE_ASYNCHRONOUS){
offset_pgpio = (priv->sin_id << 4) + 4;
putData(clk_div,priv->pgpio_base,offset_pgpio);
}
//CTRL
uint32_t ctrl;
uint32_t chg_stopbits;
priv->data_bits = bits;
ctrl = (bits + 5) << 2; //data_bits
ctrl |= (1 << parity)<<8; //parity
switch(stopbits){
case USART_STOP_BITS_0_5: chg_stopbits = 0;
case USART_STOP_BITS_1: chg_stopbits = 1;
case USART_STOP_BITS_1_5: chg_stopbits = 2;
case USART_STOP_BITS_2: chg_stopbits = 3;
}
ctrl |= chg_stopbits<<18; //stop bits
putData(ctrl,priv->prog_base_tx,USART_OFFSET_CTRL);
if(mode==USART_MODE_ASYNCHRONOUS){
ctrl |= 0x2000; //set receive_flag
putData(ctrl,priv->prog_base_rx,USART_OFFSET_CTRL);
}
return 0;
}
/**
\brief Start sending data to UART transmitter,(received data is ignored).
The function is non-blocking,UART_EVENT_TRANSFER_COMPLETE is signaled when transfer completes.
csi_usart_get_status can indicates if transmission is still in progress or pending
\param[in] handle usart handle to operate.
\param[in] data Pointer to buffer with data to send to UART transmitter. data_type is : uint8_t for 1..8 data bits, uint16_t for 9..16 data bits,uint32_t for 17..32 data bits,
\param[in] num Number of data items to send
\return error code
*/
int32_t csi_usart_send(usart_handle_t handle, const void *data, uint32_t num)
{
ck_spu_usart_priv_t *priv = handle;
priv->tx_data_buf = (void *)data;
priv->tx_total_num = num;
priv->tx_cur_num = 0;
/*
if(priv->data_bits>USART_DATA_BITS_8){
priv->tx_data_buf = (volatile uint16_t*)(data);
}else{
priv->tx_data_buf = (volatile uint8_t*)(data);
}
*/
//config: ctrl
uint32_t ctrl;
if(priv->mode==USART_MODE_SINGLE_WIRE){
getData(ctrl,priv->prog_base_tx,USART_OFFSET_CTRL);
ctrl &= 0xFFFFDFFF; //clear receive_flag
putData(ctrl,priv->prog_base_tx,USART_OFFSET_CTRL);
}
//config: INT
putData(0,priv->prog_base_tx,USART_OFFSET_INT);
//config: tx_fifo_head
uint32_t fifo_head;
fifo_head = (USART_FIFO_DEPTH << 24) | (USART_FIFO_EMPTY_TL << 16);
putData(fifo_head,priv->prog_base_tx,USART_OFFSET_FIFO_HEAD_W0);
fifo_head = (priv->prog_base_tx - priv->spu_base + USART_OFFSET_FIFO_MEM) << 14;
putData(fifo_head,priv->prog_base_tx,USART_OFFSET_FIFO_HEAD_W1);
//send data
send_data(priv);
priv->tx_busy = true;
//start PE
uint32_t pgpio_decode;
pgpio_decode = (1 << priv->sout_id);
putData(pgpio_decode,priv->global_base,OFFSET_PGPIO_START_EN);
return 0;
}
/**
\brief Abort Send data to UART transmitter
\param[in] handle usart handle to operate.
\return error code
*/
int32_t csi_usart_abort_send(usart_handle_t handle)
{
return 0;
}
/**
\brief Start receiving data from UART receiver.transmits the default value as specified by csi_usart_set_default_tx_value
\param[in] handle usart handle to operate.
\param[out] data Pointer to buffer for data to receive from UART receiver
\param[in] num Number of data items to receive
\return error code
*/
int32_t csi_usart_receive(usart_handle_t handle, void *data, uint32_t num)
{
ck_spu_usart_priv_t *priv = handle;
priv->rx_data_buf = data;
priv->rx_total_num = num;
priv->rx_cur_num = 0;
//config: ctrl
uint32_t ctrl;
uint32_t prog_base;
if(priv->mode==USART_MODE_SINGLE_WIRE){
getData(ctrl,priv->prog_base_tx,USART_OFFSET_CTRL);
ctrl |= 0x2000; //set receive_flag
putData(ctrl,priv->prog_base_tx,USART_OFFSET_CTRL);
prog_base = priv->prog_base_tx;
}
else{
prog_base = priv->prog_base_rx;
}
//config: TRANS_LEN
putData(num,prog_base,USART_OFFSET_TRANS_LEN);
//config: INT
putData(0,prog_base,USART_OFFSET_INT);
//config: rx_fifo_head
uint32_t fifo_head;
fifo_head = (USART_FIFO_DEPTH << 24) | (USART_FIFO_FULL_TL << 16);
putData(fifo_head,prog_base,USART_OFFSET_FIFO_HEAD_W0);
fifo_head = (prog_base - priv->spu_base + USART_OFFSET_FIFO_MEM) << 14;
putData(fifo_head,prog_base,USART_OFFSET_FIFO_HEAD_W1);
//start PE
uint32_t pgpio_decode;
if(priv->mode==USART_MODE_SINGLE_WIRE){
pgpio_decode = (1 << priv->sout_id);
}
else{
pgpio_decode = (1 << priv->sin_id);
}
putData(pgpio_decode,priv->global_base,OFFSET_PGPIO_START_EN);
priv->rx_busy = true;
return 0;
}
/**
\brief query data from UART receiver FIFO.
\param[in] handle usart handle to operate.
\param[out] data Pointer to buffer for data to receive from UART receiver
\param[in] num Number of data items to receive
\return receive fifo data num
*/
int32_t csi_usart_receive_query(usart_handle_t handle, void *data, uint32_t num)
{
ck_spu_usart_priv_t *priv = handle;
if(priv->rx_busy){
return 0;
}else{
return priv->rx_total_num;
}
}
/**
\brief Abort Receive data from UART receiver
\param[in] handle usart handle to operate.
\return error code
*/
int32_t csi_usart_abort_receive(usart_handle_t handle)
{
return 0;
}
/**
\brief Start sending/receiving data to/from UART transmitter/receiver.
\param[in] handle usart handle to operate.
\param[in] data_out Pointer to buffer with data to send to USART transmitter
\param[out] data_in Pointer to buffer for data to receive from USART receiver
\param[in] num Number of data items to transfer
\return error code
*/
int32_t csi_csi_usart_transfer(usart_handle_t handle, const void *data_out, void *data_in, uint32_t num)
{
return ERR_USART(DRV_ERROR_UNSUPPORTED);
}
/**
\brief abort sending/receiving data to/from USART transmitter/receiver.
\param[in] handle usart handle to operate.
\return error code
*/
int32_t csi_usart_abort_transfer(usart_handle_t handle)
{
return ERR_USART(DRV_ERROR_UNSUPPORTED);
}
/**
\brief Get USART status.
\param[in] handle usart handle to operate.
\return USART status \ref usart_status_t
*/
usart_status_t csi_usart_get_status(usart_handle_t handle)
{
ck_spu_usart_priv_t *priv = handle;
usart_status_t usart_status;
if(priv->tx_busy){
usart_status.tx_busy = 1;
}else{
usart_status.tx_busy = 0;
}
if(priv->rx_busy){
usart_status.rx_busy = 1;
}else{
usart_status.rx_busy = 0;
}
return usart_status;
}
/**
\brief control the transmit.
\param[in] handle usart handle to operate.
\param[in] enable the transmitter.
\return error code
*/
int32_t csi_usart_control_tx(usart_handle_t handle, uint32_t enable)
{
return ERR_USART(DRV_ERROR_UNSUPPORTED);
}
/**
\brief control the receive.
\param[in] handle usart handle to operate.
\param[in] enable the receive.
\return error code
*/
int32_t csi_usart_control_rx(usart_handle_t handle, uint32_t enable)
{
return ERR_USART(DRV_ERROR_UNSUPPORTED);
}
/**
\brief control the break.
\param[in] handle usart handle to operate.
\param[in] enable the break.
\return error code
*/
int32_t csi_usart_control_break(usart_handle_t handle, uint32_t enable)
{
return ERR_USART(DRV_ERROR_UNSUPPORTED);
}
/**
\brief flush receive/send data.
\param[in] handle usart handle to operate.
\param[in] type \ref usart_flush_type_e.
\return error code
*/
int32_t csi_usart_flush(usart_handle_t handle, usart_flush_type_e type)
{
return ERR_USART(DRV_ERROR_UNSUPPORTED);
//return 0;
}

View file

@ -0,0 +1,4 @@
!.gitignore
bin
tee.ld

View file

@ -0,0 +1,37 @@
#
# Makefile for TEE
#
TARGETS_ROOT_PATH ?=
TEEOS_LIB_PATH ?=
TEEOS_LIB ?=
TARGET_TEE ?= bin/$(TEEOS_LIB:lib%.a=%)
CC = csky-abiv2-elf-gcc
OBJDUMP = csky-abiv2-elf-objdump
OBJCOPY = csky-abiv2-elf-objcopy
ASFLAGS := -c -Os -mcpu=ck802t -Wa,--gdwarf2 -Wa,-melrw
LDFLAGS := -mcpu=ck802t -nostartfiles -Wl,--gc-sections -fno-builtin
TEE_LD := tee.ld
.PHONY: clean
all: $(TARGET_TEE)
$(TARGET_TEE) : $(TEE_LD) $(TEEOS_LIB_PATH)/$(TEEOS_LIB)
@echo TEELINK $@
@mkdir -p bin
@$(CC) $(LDFLAGS) -Wl,-ckmap='$@.map' -T$(TEE_LD) -o $@ -Wl,--whole-archive $(TEEOS_LIB_PATH)/$(TEEOS_LIB) -Wl,--no-whole-archive
$(OBJDUMP) -d $@ > $@.dump
$(OBJCOPY) -O binary -R .note -R .comment $@ $@.bin
$(OBJCOPY) -O ihex $@ $@.hex
$(TEE_LD) : $(TEE_LD).S
@echo TEECC $@ $(TEEOS_LIB_PATH)
@$(CC) -I$(TEEOS_LIB_PATH) -I$(TARGETS_ROOT_PATH)/include -P -E -o $@ $<
clean:
@-rm -fr bin $(TEE_LD)

View file

@ -0,0 +1,60 @@
#include "tee_addr_map.h"
ENTRY(_start)
MEMORY
{
FLASH : ORIGIN = TW_RO_ADDR, LENGTH = TW_RO_SIZE
ISRAM : ORIGIN = TW_RW_ADDR, LENGTH = TW_RW_SIZE
}
SECTIONS
{
.text : {
. = ALIGN(0x4);
__text_start = .;
*(.text)
*(.text*)
. = ALIGN(0x4);
__text_end = .;
} > FLASH
.rodata : {
. = ALIGN(0x4);
__rodata_start = .;
KEEP(*(.rodata))
KEEP(*(.rodata*))
. = ALIGN(0x4);
KEEP(*(SORT(.table.*)))
. = ALIGN(0x4);
__srvdata_start = .;
KEEP(*(.srv.data))
KEEP(*(.srv.data*))
__srvdata_end = .;
. = ALIGN(0x4);
__rodata_end = .;
} > FLASH
__data_copy_start = .;
.data : AT(__data_copy_start) {
. = ALIGN(0x4);
__data_start = .;
KEEP(*(.exp_table))
KEEP(*(.data))
KEEP(*(.data*))
. = ALIGN(0x4);
__data_end = .;
} > ISRAM
.bss : AT(ADDR(.data) + SIZEOF(.data)) {
. = ALIGN(0x4);
__bss_start = .;
KEEP(*(.bss))
KEEP(*(.bss*))
*(COMMON*)
. = ALIGN(0x4);
__bss_end = .;
} > ISRAM
}

View file

@ -0,0 +1,329 @@
/*
* Copyright (C) 2017 C-SKY Microsystems Co., Ltd. All rights reserved.
*
* 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 dw_timer.c
* @brief CSI Source File for timer Driver
* @version V1.0
* @date 02. June 2017
******************************************************************************/
#include <csi_config.h>
#include "drv_timer.h"
#include "dw_timer.h"
#include "soc.h"
#include "csi_core.h"
#define ERR_TIMER(errno) (CSI_DRV_ERRNO_TIMER_BASE | errno)
#define TIMER_NULL_PARAM_CHK(para) \
do { \
if (para == NULL) { \
return ERR_TIMER(DRV_ERROR_PARAMETER); \
} \
} while (0)
typedef struct {
uint32_t base;
uint32_t irq;
timer_event_cb_t cb_event;
uint32_t timeout; ///< the set time (us)
uint32_t timeout_flag;
} dw_timer_priv_t;
extern int32_t target_get_timer_count(void);
extern int32_t target_get_timer(int32_t idx, uint32_t *base, uint32_t *irq);
static dw_timer_priv_t timer_instance[CONFIG_TIMER_NUM];
/**
\brief Make all the timers in the idle state.
\param[in] pointer to timer register base
*/
static void timer_deactive_control(dw_timer_reg_t *addr)
{
/* stop the corresponding timer */
addr->TxControl &= ~DW_TIMER_TXCONTROL_ENABLE;
/* Disable interrupt. */
addr->TxControl |= DW_TIMER_TXCONTROL_INTMASK;
}
void dw_timer_irqhandler(int idx)
{
dw_timer_priv_t *timer_priv = &timer_instance[idx];
timer_priv->timeout_flag = 1;
dw_timer_reg_t *addr = (dw_timer_reg_t *)(timer_priv->base);
addr->TxEOI;
if (timer_priv->cb_event) {
return timer_priv->cb_event(idx, TIMER_EVENT_TIMEOUT);
}
}
/**
\brief Initialize TIMER Interface. 1. Initializes the resources needed for the TIMER interface 2.registers event callback function
\param[in] idx instance timer index
\param[in] cb_event Pointer to \ref timer_event_cb_t
\return pointer to timer instance
*/
timer_handle_t csi_timer_initialize(int32_t idx, timer_event_cb_t cb_event)
{
if (idx < 0 || idx >= CONFIG_TIMER_NUM) {
return NULL;
}
uint32_t base = 0u;
uint32_t irq = 0u;
int32_t real_idx = target_get_timer(idx, &base, &irq);
if (real_idx != idx) {
return NULL;
}
dw_timer_priv_t *timer_priv = &timer_instance[idx];
timer_priv->base = base;
timer_priv->irq = irq;
dw_timer_reg_t *addr = (dw_timer_reg_t *)(timer_priv->base);
timer_priv->timeout = DW_TIMER_INIT_DEFAULT_VALUE;
timer_deactive_control(addr);
timer_priv->cb_event = cb_event;
if (cb_event != NULL) {
csi_vic_enable_irq(timer_priv->irq);
}
return (timer_handle_t)timer_priv;
}
/**
\brief De-initialize TIMER Interface. stops operation and releases the software resources used by the interface
\param[in] handle timer handle to operate.
\return error code
*/
int32_t csi_timer_uninitialize(timer_handle_t handle)
{
TIMER_NULL_PARAM_CHK(handle);
dw_timer_priv_t *timer_priv = (dw_timer_priv_t *)handle;
dw_timer_reg_t *addr = (dw_timer_reg_t *)(timer_priv->base);
timer_deactive_control(addr);
timer_priv->cb_event = NULL;
csi_vic_disable_irq(timer_priv->irq);
return 0;
}
/**
\brief config timer mode.
\param[in] handle timer handle to operate.
\param[in] mode \ref timer_mode_e
\return error code
*/
int32_t csi_timer_config(timer_handle_t handle, timer_mode_e mode)
{
TIMER_NULL_PARAM_CHK(handle);
dw_timer_priv_t *timer_priv = handle;
dw_timer_reg_t *addr = (dw_timer_reg_t *)(timer_priv->base);
switch (mode) {
case TIMER_MODE_FREE_RUNNING:
addr->TxControl &= ~DW_TIMER_TXCONTROL_MODE;
break;
case TIMER_MODE_RELOAD:
addr->TxControl |= DW_TIMER_TXCONTROL_MODE;
break;
default:
return ERR_TIMER(DRV_ERROR_PARAMETER);
}
return 0;
}
/**
\brief Set timer.
\param[in] instance timer instance to operate.
\param[in] timeout the timeout value in microseconds(us).
\return error code
*/
int32_t csi_timer_set_timeout(timer_handle_t handle, uint32_t timeout)
{
TIMER_NULL_PARAM_CHK(handle);
dw_timer_priv_t *timer_priv = handle;
timer_priv->timeout = timeout;
return 0;
}
/**
\brief Start timer.
\param[in] handle timer handle to operate.
\return error code
*/
int32_t csi_timer_start(timer_handle_t handle)
{
TIMER_NULL_PARAM_CHK(handle);
dw_timer_priv_t *timer_priv = handle;
timer_priv->timeout_flag = 0;
uint32_t min_us = LSP_DEFAULT_FREQ / 1000000;
uint32_t load;
if (timer_priv->timeout > 0xffffffff / min_us) {
return ERR_TIMER(DRV_ERROR_PARAMETER);
}
if (min_us) {
load = (uint32_t)(timer_priv->timeout * min_us);
} else {
load = (uint32_t)(((timer_priv->timeout) * LSP_DEFAULT_FREQ) / 1000000);
}
dw_timer_reg_t *addr = (dw_timer_reg_t *)(timer_priv->base);
if (timer_priv->timeout == 0) {
addr->TxLoadCount = 0xffffffff; /* load time(us) */
} else {
addr->TxLoadCount = load; /* load time(us) */
}
addr->TxControl &= ~DW_TIMER_TXCONTROL_ENABLE; /* disable the timer */
addr->TxControl |= DW_TIMER_TXCONTROL_ENABLE; /* enable the corresponding timer */
addr->TxControl &= ~DW_TIMER_TXCONTROL_INTMASK; /* enable interrupt */
return 0;
}
/**
\brief Stop timer.
\param[in] handle timer handle to operate.
\return error code
*/
int32_t csi_timer_stop(timer_handle_t handle)
{
TIMER_NULL_PARAM_CHK(handle);
dw_timer_priv_t *timer_priv = handle;
dw_timer_reg_t *addr = (dw_timer_reg_t *)(timer_priv->base);
addr->TxControl |= DW_TIMER_TXCONTROL_INTMASK; /* enable interrupt */
addr->TxControl &= ~DW_TIMER_TXCONTROL_ENABLE; /* disable the timer */
return 0;
}
/**
\brief suspend timer.
\param[in] instance timer instance to operate.
\return error code
*/
int32_t csi_timer_suspend(timer_handle_t handle)
{
TIMER_NULL_PARAM_CHK(handle);
return ERR_TIMER(DRV_ERROR_UNSUPPORTED);
}
/**
\brief resume timer.
\param[in] handle timer handle to operate.
\return error code
*/
int32_t csi_timer_resume(timer_handle_t handle)
{
TIMER_NULL_PARAM_CHK(handle);
dw_timer_priv_t *timer_priv = handle;
dw_timer_reg_t *addr = (dw_timer_reg_t *)(timer_priv->base);
addr->TxControl &= ~DW_TIMER_TXCONTROL_ENABLE; /* stop the corresponding timer */
addr->TxControl &= DW_TIMER_TXCONTROL_ENABLE; /* restart the corresponding timer */
return 0;
}
/**
\brief get timer current value
\param[in] handle timer handle to operate.
\param[out] value timer current value
\return error code
*/
int32_t csi_timer_get_current_value(timer_handle_t handle, uint32_t *value)
{
TIMER_NULL_PARAM_CHK(handle);
TIMER_NULL_PARAM_CHK(value);
dw_timer_priv_t *timer_priv = handle;
dw_timer_reg_t *addr = (dw_timer_reg_t *)(timer_priv->base);
*value = addr->TxCurrentValue;
return 0;
}
/**
\brief Get TIMER status.
\param[in] handle timer handle to operate.
\return TIMER status \ref timer_status_t
*/
timer_status_t csi_timer_get_status(timer_handle_t handle)
{
timer_status_t timer_status = {0};
if (handle == NULL) {
return timer_status;
}
dw_timer_priv_t *timer_priv = handle;
dw_timer_reg_t *addr = (dw_timer_reg_t *)(timer_priv->base);
if (addr->TxControl & DW_TIMER_TXCONTROL_ENABLE) {
timer_status.active = 1;
}
if (timer_priv->timeout_flag == 1) {
timer_status.timeout = 1;
}
return timer_status;
}
/**
\brief get timer reload value
\param[in] handle timer handle to operate.
\param[out] value timer reload value
\return error code
*/
int32_t csi_timer_get_load_value(timer_handle_t handle, uint32_t *value)
{
TIMER_NULL_PARAM_CHK(handle);
TIMER_NULL_PARAM_CHK(value);
dw_timer_priv_t *timer_priv = handle;
dw_timer_reg_t *addr = (dw_timer_reg_t *)(timer_priv->base);
*value = addr->TxLoadCount;
return 0;
}

View file

@ -0,0 +1,234 @@
/*
* Copyright (C) 2017 C-SKY Microsystems Co., Ltd. All rights reserved.
*
* 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 ck_trng.c
* @brief CSI Source File for TRNG Driver
* @version V1.0
* @date 02. June 2017
******************************************************************************/
#include <csi_config.h>
#include <stdbool.h>
#include <stdio.h>
#include <string.h>
#include "drv_trng.h"
#include "ck_trng.h"
#define ERR_TRNG(errno) (CSI_DRV_ERRNO_TRNG_BASE | errno)
#define TRNG_NULL_PARAM_CHK(para) \
do { \
if (para == NULL) { \
return ERR_TRNG(DRV_ERROR_PARAMETER); \
} \
} while (0)
typedef struct {
uint32_t base;
trng_event_cb_t cb;
trng_status_t status;
} ck_trng_priv_t;
extern int32_t target_get_trng_count(void);
extern int32_t target_get_trng(int32_t idx, uint32_t *base);
static ck_trng_priv_t trng_handle[CONFIG_TRNG_NUM];
/* Driver Capabilities */
static const trng_capabilities_t driver_capabilities = {
.lowper_mode = 0 /* low power mode */
};
//
// Functions
//
ck_trng_reg_t *trng_reg = NULL;
static int32_t trng_enable(void)
{
trng_reg->TCR |= TRNG_EN;
return 0;
}
static int32_t trng_get_data(void)
{
int data = trng_reg->TDR;
return data;
}
static int32_t trng_data_is_ready(void)
{
int flag = (trng_reg->TCR & TRNG_DATA_READY);
return flag;
}
/**
\brief Initialize TRNG Interface. 1. Initializes the resources needed for the TRNG interface 2.registers event callback function
\param[in] idx device id
\param[in] cb_event Pointer to \ref trng_event_cb_t
\return pointer to trng handle
*/
trng_handle_t csi_trng_initialize(int32_t idx, trng_event_cb_t cb_event)
{
if (idx < 0 || idx >= CONFIG_TRNG_NUM) {
return NULL;
}
/* obtain the trng information */
uint32_t base = 0u;
int32_t real_idx = target_get_trng(idx, &base);
if (real_idx != idx) {
return NULL;
}
ck_trng_priv_t *trng_priv = &trng_handle[idx];
trng_priv->base = base;
/* initialize the trng context */
trng_reg = (ck_trng_reg_t *)(trng_priv->base);
trng_priv->cb = cb_event;
trng_priv->status.busy = 0;
trng_priv->status.data_valid = 0;
return (trng_handle_t)trng_priv;
}
/**
\brief De-initialize TRNG Interface. stops operation and releases the software resources used by the interface
\param[in] handle trng handle to operate.
\return error code
*/
int32_t csi_trng_uninitialize(trng_handle_t handle)
{
TRNG_NULL_PARAM_CHK(handle);
ck_trng_priv_t *trng_priv = handle;
trng_priv->cb = NULL;
return 0;
}
/**
\brief Get driver capabilities.
\param[in] idx device id.
\return \ref trng_capabilities_t
*/
trng_capabilities_t csi_trng_get_capabilities(int32_t idx)
{
if (idx < 0 || idx >= CONFIG_TRNG_NUM) {
trng_capabilities_t ret;
memset(&ret, 0, sizeof(trng_capabilities_t));
return ret;
}
return driver_capabilities;
}
/**
\brief Get data from the TRNG.
\param[in] handle trng handle to operate.
\param[out] data Pointer to buffer with data get from TRNG
\param[in] num Number of data items to obtain
\return error code
*/
int32_t csi_trng_get_data(trng_handle_t handle, void *data, uint32_t num)
{
TRNG_NULL_PARAM_CHK(handle);
TRNG_NULL_PARAM_CHK(data);
TRNG_NULL_PARAM_CHK(num);
ck_trng_priv_t *trng_priv = handle;
trng_priv->status.busy = 1U;
trng_priv->status.data_valid = 0U;
uint8_t left_len = (uint32_t)data & 0x3;
uint32_t result = 0;
/* if the data addr is not aligned by word */
if (left_len) {
trng_enable();
while (!trng_data_is_ready());
result = trng_get_data();
/* wait the data is ready */
while (trng_data_is_ready());
if (num > (4 - left_len)) {
memcpy(data, &result, 4 - left_len);
} else {
memcpy(data, &result, num);
trng_priv->status.busy = 0U;
trng_priv->status.data_valid = 1U;
if (trng_priv->cb) {
trng_priv->cb(0, TRNG_EVENT_DATA_GENERATE_COMPLETE);
}
return 0;
}
num -= (4 - left_len);
data += (4 - left_len);
}
uint32_t word_len = num >> 2;
left_len = num & 0x3;
/* obtain the data by word */
while (word_len--) {
trng_enable();
while (!trng_data_is_ready());
result = trng_get_data();
while (trng_data_is_ready());
*(uint32_t *)data = result;
data = (void *)((uint32_t)data + 4);
}
/* if the num is not aligned by word */
if (left_len) {
trng_enable();
while (!trng_data_is_ready());
result = trng_get_data();
while (trng_data_is_ready());
memcpy(data, &result, left_len);
}
trng_priv->status.busy = 0U;
trng_priv->status.data_valid = 1U;
if (trng_priv->cb) {
trng_priv->cb(0, TRNG_EVENT_DATA_GENERATE_COMPLETE);
}
return 0;
}
/**
\brief Get TRNG status.
\param[in] handle trng handle to operate.
\return TRNG status \ref trng_status_t
*/
trng_status_t csi_trng_get_status(trng_handle_t handle)
{
if (handle == NULL) {
trng_status_t ret;
memset(&ret, 0, sizeof(trng_status_t));
return ret;
}
ck_trng_priv_t *trng_priv = handle;
return trng_priv->status;
}

View file

@ -0,0 +1,700 @@
/*
* Copyright (C) 2017 C-SKY Microsystems Co., Ltd. All rights reserved.
*
* 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 ck_usart.c
* @brief CSI Source File for usart Driver
* @version V1.0
* @date 02. June 2017
******************************************************************************/
#include <csi_config.h>
#include <stdbool.h>
#include <string.h>
#include "drv_usart.h"
#include "ck_usart.h"
#include "soc.h"
#include "csi_core.h"
#define ERR_USART(errno) (CSI_DRV_ERRNO_USART_BASE | errno)
/*
* setting config may be accessed when the USART is not
* busy(USR[0]=0) and the DLAB bit(LCR[7]) is set.
*/
#define WAIT_USART_IDLE(addr)\
do { \
int32_t timecount = 0; \
while ((addr->USR & USR_UART_BUSY) && (timecount < UART_BUSY_TIMEOUT)) {\
timecount++;\
}\
if (timecount >= UART_BUSY_TIMEOUT) {\
return ERR_USART(DRV_ERROR_TIMEOUT);\
} \
} while(0)
#define USART_NULL_PARAM_CHK(para) \
do { \
if (para == NULL) { \
return ERR_USART(DRV_ERROR_PARAMETER); \
} \
} while (0)
typedef struct {
uint32_t base;
uint32_t irq;
usart_event_cb_t cb_event; ///< Event callback
uint32_t rx_total_num;
uint32_t tx_total_num;
uint8_t *rx_buf;
uint8_t *tx_buf;
volatile uint32_t rx_cnt;
volatile uint32_t tx_cnt;
volatile uint32_t tx_busy;
volatile uint32_t rx_busy;
} dw_usart_priv_t;
extern int32_t target_usart_init(int32_t idx, uint32_t *base, uint32_t *irq);
static dw_usart_priv_t usart_instance[CONFIG_USART_NUM];
static const usart_capabilities_t usart_capabilities = {
.asynchronous = 1, /* supports USART (Asynchronous) mode */
.synchronous_master = 0, /* supports Synchronous Master mode */
.synchronous_slave = 0, /* supports Synchronous Slave mode */
.single_wire = 0, /* supports USART Single-wire mode */
.event_tx_complete = 1, /* Transmit completed event */
.event_rx_timeout = 0, /* Signal receive character timeout event */
};
/**
\brief set the bautrate of usart.
\param[in] addr usart base to operate.
\param[in] baudrate.
\param[in] apbfreq the frequence of the apb.
\return error code
*/
static int32_t dw_usart_set_baudrate(dw_usart_reg_t *addr, uint32_t baudrate)
{
WAIT_USART_IDLE(addr);
/* baudrate=(seriak clock freq)/(16*divisor); algorithm :rounding*/
uint32_t divisor = ((LSP_DEFAULT_FREQ * 10) / baudrate) >> 4;
if ((divisor % 10) >= 5) {
divisor = (divisor / 10) + 1;
} else {
divisor = divisor / 10;
}
addr->LCR |= LCR_SET_DLAB;
/* DLL and DLH is lower 8-bits and higher 8-bits of divisor.*/
addr->DLL = divisor & 0xff;
addr->DLH = (divisor >> 8) & 0xff;
/*
* The DLAB must be cleared after the baudrate is setted
* to access other registers.
*/
addr->LCR &= (~LCR_SET_DLAB);
return 0;
}
/**
\brief enable or disable parity.
\param[in] addr usart base to operate.
\param[in] parity ODD=8, EVEN=16, or NONE=0.
\return error code
*/
static int32_t dw_usart_set_parity(dw_usart_reg_t *addr, usart_parity_e parity)
{
WAIT_USART_IDLE(addr);
switch (parity) {
case USART_PARITY_NONE:
/*CLear the PEN bit(LCR[3]) to disable parity.*/
addr->LCR &= (~LCR_PARITY_ENABLE);
break;
case USART_PARITY_ODD:
/* Set PEN and clear EPS(LCR[4]) to set the ODD parity. */
addr->LCR |= LCR_PARITY_ENABLE;
addr->LCR &= LCR_PARITY_ODD;
break;
case USART_PARITY_EVEN:
/* Set PEN and EPS(LCR[4]) to set the EVEN parity.*/
addr->LCR |= LCR_PARITY_ENABLE;
addr->LCR |= LCR_PARITY_EVEN;
break;
default:
return ERR_USART(USART_ERROR_PARITY);
}
return 0;
}
/**
\brief set the stop bit.
\param[in] addr usart base to operate.
\param[in] stopbit two possible value: USART_STOP_BITS_1 and USART_STOP_BITS_2.
\return error code
*/
static int32_t dw_usart_set_stopbit(dw_usart_reg_t *addr, usart_stop_bits_e stopbit)
{
WAIT_USART_IDLE(addr);
switch (stopbit) {
case USART_STOP_BITS_1:
/* Clear the STOP bit to set 1 stop bit*/
addr->LCR &= LCR_STOP_BIT1;
break;
case USART_STOP_BITS_2:
/*
* If the STOP bit is set "1",we'd gotten 1.5 stop
* bits when DLS(LCR[1:0]) is zero, else 2 stop bits.
*/
addr->LCR |= LCR_STOP_BIT2;
break;
default:
return ERR_USART(USART_ERROR_STOP_BITS);
}
return 0;
}
/**
\brief the transmit data length,and we have four choices:5, 6, 7, and 8 bits.
\param[in] addr usart base to operate.
\param[in] databits the data length that user decides.
\return error code
*/
static int32_t dw_usart_set_databit(dw_usart_reg_t *addr, usart_data_bits_e databits)
{
WAIT_USART_IDLE(addr);
/* The word size decides by the DLS bits(LCR[1:0]), and the
* corresponding relationship between them is:
* DLS word size
* 00 -- 5 bits
* 01 -- 6 bits
* 10 -- 7 bits
* 11 -- 8 bits
*/
switch (databits) {
case USART_DATA_BITS_5:
addr->LCR &= LCR_WORD_SIZE_5;
break;
case USART_DATA_BITS_6:
addr->LCR &= 0xfd;
addr->LCR |= LCR_WORD_SIZE_6;
break;
case USART_DATA_BITS_7:
addr->LCR &= 0xfe;
addr->LCR |= LCR_WORD_SIZE_7;
break;
case USART_DATA_BITS_8:
addr->LCR |= LCR_WORD_SIZE_8;
break;
default:
return ERR_USART(USART_ERROR_DATA_BITS);
}
return 0;
}
/**
\brief get character in query mode.
\param[in] instance usart instance to operate.
\param[in] the pointer to the recieve charater.
\return error code
*/
int32_t csi_usart_getchar(usart_handle_t handle, uint8_t *ch)
{
dw_usart_priv_t *usart_priv = handle;
dw_usart_reg_t *addr = (dw_usart_reg_t *)(usart_priv->base);
while (!(addr->LSR & LSR_DATA_READY));
*ch = addr->RBR;
return 0;
}
/**
\brief transmit character in query mode.
\param[in] instance usart instance to operate.
\param[in] ch the input charater
\return error code
*/
int32_t csi_usart_putchar(usart_handle_t handle, uint8_t ch)
{
dw_usart_priv_t *usart_priv = handle;
dw_usart_reg_t *addr = (dw_usart_reg_t *)(usart_priv->base);
while ((!(addr->LSR & DW_LSR_TRANS_EMPTY)));
addr->THR = ch;
return 0;
}
/**
\brief interrupt service function for transmitter holding register empty.
\param[in] usart_priv usart private to operate.
*/
static void dw_usart_intr_threshold_empty(int32_t idx,dw_usart_priv_t *usart_priv)
{
if (usart_priv->tx_total_num == 0) {
return;
}
dw_usart_reg_t *addr = (dw_usart_reg_t *)(usart_priv->base);
addr->THR = *((uint8_t *)usart_priv->tx_buf);
usart_priv->tx_cnt++;
usart_priv->tx_buf++;
if (usart_priv->tx_cnt >= usart_priv->tx_total_num) {
addr->IER &= (~IER_THRE_INT_ENABLE);
while ((!(addr->LSR & DW_LSR_TEMT)));
usart_priv->tx_cnt = 0;
usart_priv->tx_busy = 0;
usart_priv->tx_buf = NULL;
usart_priv->tx_total_num = 0;
if (usart_priv->cb_event) {
usart_priv->cb_event(idx, USART_EVENT_SEND_COMPLETE);
}
}
}
/**
\brief interrupt service function for receiver data available.
\param[in] usart_priv usart private to operate.
*/
static void dw_usart_intr_recv_data(int32_t idx, dw_usart_priv_t *usart_priv)
{
if (usart_priv->cb_event && (usart_priv->rx_total_num == 0)) {
usart_priv->cb_event(idx, USART_EVENT_RECEIVED);
return;
}
dw_usart_reg_t *addr = (dw_usart_reg_t *)(usart_priv->base);
uint8_t data = addr->RBR;
if ((usart_priv->rx_total_num == 0) || (usart_priv->rx_buf == NULL)) {
return;
}
*((uint8_t *)usart_priv->rx_buf) = data;
usart_priv->rx_cnt++;
usart_priv->rx_buf++;
if (usart_priv->rx_cnt >= usart_priv->rx_total_num) {
usart_priv->rx_cnt = 0;
usart_priv->rx_buf = NULL;
usart_priv->rx_busy = 0;
usart_priv->rx_total_num = 0;
if (usart_priv->cb_event) {
usart_priv->cb_event(idx, USART_EVENT_RECEIVE_COMPLETE);
}
}
}
/**
\brief the interrupt service function.
\param[in] index of usart instance.
*/
void dw_usart_irqhandler(int32_t idx)
{
dw_usart_priv_t *usart_priv = &usart_instance[idx];
dw_usart_reg_t *addr = (dw_usart_reg_t *)(usart_priv->base);
uint8_t intr_state = addr->IIR & 0xf;
switch (intr_state) {
case DW_IIR_THR_EMPTY: /* interrupt source:transmitter holding register empty */
dw_usart_intr_threshold_empty(idx, usart_priv);
break;
case DW_IIR_RECV_DATA: /* interrupt source:receiver data available or receiver fifo trigger level reached */
dw_usart_intr_recv_data(idx, usart_priv);
break;
default:
break;
}
}
/**
\brief Get driver capabilities.
\param[in] idx usart index
\return \ref usart_capabilities_t
*/
usart_capabilities_t csi_usart_get_capabilities(int32_t idx)
{
if (idx < 0 || idx >= CONFIG_USART_NUM) {
usart_capabilities_t ret;
memset(&ret, 0, sizeof(usart_capabilities_t));
return ret;
}
return usart_capabilities;
}
/**
\brief Initialize USART Interface. 1. Initializes the resources needed for the USART interface 2.registers event callback function
\param[in] idx usart index
\param[in] cb_event Pointer to \ref usart_event_cb_t
\return return usart handle if success
*/
usart_handle_t csi_usart_initialize(int32_t idx, usart_event_cb_t cb_event)
{
uint32_t base = 0u;
uint32_t irq = 0u;
int32_t ret = target_usart_init(idx, &base, &irq);
if (ret < 0 || ret >= CONFIG_USART_NUM) {
return NULL;
}
dw_usart_priv_t *usart_priv = &usart_instance[idx];
usart_priv->base = base;
usart_priv->irq = irq;
usart_priv->cb_event = cb_event;
dw_usart_reg_t *addr = (dw_usart_reg_t *)(usart_priv->base);
/* enable received data available */
addr->IER = IER_RDA_INT_ENABLE;
csi_vic_enable_irq(usart_priv->irq);
return usart_priv;
}
/**
\brief De-initialize UART Interface. stops operation and releases the software resources used by the interface
\param[in] handle usart handle to operate.
\return error code
*/
int32_t csi_usart_uninitialize(usart_handle_t handle)
{
USART_NULL_PARAM_CHK(handle);
dw_usart_priv_t *usart_priv = handle;
csi_vic_disable_irq(usart_priv->irq);
usart_priv->cb_event = NULL;
return 0;
}
/**
\brief config usart mode.
\param[in] handle usart handle to operate.
\param[in] mode \ref usart_mode_e
\param[in] parity \ref usart_parity_e
\param[in] stopbits \ref usart_stop_bits_e
\param[in] bits \ref usart_data_bits_e
\param[in] baud configured baud
\return error code
*/
int32_t csi_usart_config(usart_handle_t handle,
uint32_t baud,
usart_mode_e mode,
usart_parity_e parity,
usart_stop_bits_e stopbits,
usart_data_bits_e bits)
{
USART_NULL_PARAM_CHK(handle);
dw_usart_priv_t *usart_priv = handle;
dw_usart_reg_t *addr = (dw_usart_reg_t *)(usart_priv->base);
/* control the data_bit of the usart*/
int32_t ret = dw_usart_set_baudrate(addr, baud);
if (ret < 0) {
return ret;
}
/* control the parity of the usart*/
ret = dw_usart_set_parity(addr, parity);
if (ret < 0) {
return ret;
}
/* control the stopbit of the usart*/
ret = dw_usart_set_stopbit(addr, stopbits);
if (ret < 0) {
return ret;
}
ret = dw_usart_set_databit(addr, bits);
if (ret < 0) {
return ret;
}
return 0;
}
/**
\brief Start sending data to UART transmitter,(received data is ignored).
The function is non-blocking,UART_EVENT_TRANSFER_COMPLETE is signaled when transfer completes.
csi_usart_get_status can indicates if transmission is still in progress or pending
\param[in] handle usart handle to operate.
\param[in] data Pointer to buffer with data to send to UART transmitter. data_type is : uint8_t for 1..8 data bits, uint16_t for 9..16 data bits,uint32_t for 17..32 data bits,
\param[in] num Number of data items to send
\return error code
*/
int32_t csi_usart_send(usart_handle_t handle, const void *data, uint32_t num)
{
USART_NULL_PARAM_CHK(handle);
USART_NULL_PARAM_CHK(data);
if (num == 0) {
return ERR_USART(DRV_ERROR_PARAMETER);
}
dw_usart_priv_t *usart_priv = handle;
usart_priv->tx_buf = (uint8_t *)data;
usart_priv->tx_total_num = num;
usart_priv->tx_cnt = 0;
usart_priv->tx_busy = 1;
dw_usart_reg_t *addr = (dw_usart_reg_t *)(usart_priv->base);
/* enable the interrupt*/
addr->IER |= IER_THRE_INT_ENABLE;
return 0;
}
/**
\brief Abort Send data to UART transmitter
\param[in] handle usart handle to operate.
\return error code
*/
int32_t csi_usart_abort_send(usart_handle_t handle)
{
USART_NULL_PARAM_CHK(handle);
dw_usart_priv_t *usart_priv = handle;
usart_priv->tx_cnt = usart_priv->tx_total_num;
return 0;
}
/**
\brief Start receiving data from UART receiver.transmits the default value as specified by csi_usart_set_default_tx_value
\param[in] handle usart handle to operate.
\param[out] data Pointer to buffer for data to receive from UART receiver
\param[in] num Number of data items to receive
\return error code
*/
int32_t csi_usart_receive(usart_handle_t handle, void *data, uint32_t num)
{
USART_NULL_PARAM_CHK(handle);
USART_NULL_PARAM_CHK(data);
dw_usart_priv_t *usart_priv = handle;
usart_priv->rx_buf = (uint8_t *)data; // Save receive buffer usart
usart_priv->rx_total_num = num; // Save number of data to be received
usart_priv->rx_cnt = 0;
usart_priv->rx_busy = 1;
return 0;
}
/**
\brief query data from UART receiver FIFO.
\param[in] handle usart handle to operate.
\param[out] data Pointer to buffer for data to receive from UART receiver
\param[in] num Number of data items to receive
\return receive fifo data num
*/
int32_t csi_usart_receive_query(usart_handle_t handle, void *data, uint32_t num)
{
USART_NULL_PARAM_CHK(handle);
USART_NULL_PARAM_CHK(data);
dw_usart_priv_t *usart_priv = handle;
dw_usart_reg_t *addr = (dw_usart_reg_t *)(usart_priv->base);
int32_t recv_num = 0;
while (addr->LSR & 0x1) {
*((uint8_t *)data++) = addr->RBR;
recv_num++;
if (recv_num >= num) {
break;
}
}
return recv_num;
}
/**
\brief Abort Receive data from UART receiver
\param[in] handle usart handle to operate.
\return error code
*/
int32_t csi_usart_abort_receive(usart_handle_t handle)
{
USART_NULL_PARAM_CHK(handle);
dw_usart_priv_t *usart_priv = handle;
usart_priv->rx_cnt = usart_priv->rx_total_num;
return 0;
}
/**
\brief Start sending/receiving data to/from UART transmitter/receiver.
\param[in] handle usart handle to operate.
\param[in] data_out Pointer to buffer with data to send to USART transmitter
\param[out] data_in Pointer to buffer for data to receive from USART receiver
\param[in] num Number of data items to transfer
\return error code
*/
int32_t csi_usart_transfer(usart_handle_t handle, const void *data_out, void *data_in, uint32_t num)
{
USART_NULL_PARAM_CHK(handle);
return ERR_USART(DRV_ERROR_UNSUPPORTED);
}
/**
\brief abort sending/receiving data to/from USART transmitter/receiver.
\param[in] handle usart handle to operate.
\return error code
*/
int32_t csi_usart_abort_transfer(usart_handle_t handle)
{
USART_NULL_PARAM_CHK(handle);
return ERR_USART(DRV_ERROR_UNSUPPORTED);
}
/**
\brief Get USART status.
\param[in] handle usart handle to operate.
\return USART status \ref usart_status_t
*/
usart_status_t csi_usart_get_status(usart_handle_t handle)
{
usart_status_t usart_status;
dw_usart_priv_t *usart_priv = handle;
dw_usart_reg_t *addr = (dw_usart_reg_t *)(usart_priv->base);
uint32_t line_status_reg = addr->LSR;
usart_status.tx_busy = usart_priv->tx_busy;
usart_status.rx_busy = usart_priv->rx_busy;
if (line_status_reg & DW_LSR_BI) {
usart_status.rx_break = 1;
}
if (line_status_reg & DW_LSR_FE) {
usart_status.rx_framing_error = 1;
}
if (line_status_reg & DW_LSR_PE) {
usart_status.rx_parity_error = 1;
}
return usart_status;
}
/**
\brief control the transmit.
\param[in] handle usart handle to operate.
\param[in] 1 - enable the transmitter. 0 - disable the transmitter
\return error code
*/
int32_t csi_usart_control_tx(usart_handle_t handle, uint32_t enable)
{
USART_NULL_PARAM_CHK(handle);
return 0;
}
/**
\brief control the receive.
\param[in] handle usart handle to operate.
\param[in] 1 - enable the receiver. 0 - disable the receiver
\return error code
*/
int32_t csi_usart_control_rx(usart_handle_t handle, uint32_t enable)
{
USART_NULL_PARAM_CHK(handle);
return 0;
}
/**
\brief control the break.
\param[in] handle usart handle to operate.
\param[in] 1- Enable continuous Break transmission,0 - disable continuous Break transmission
\return error code
*/
int32_t csi_usart_control_break(usart_handle_t handle, uint32_t enable)
{
USART_NULL_PARAM_CHK(handle);
return ERR_USART(DRV_ERROR_UNSUPPORTED);
}
/**
\brief flush receive/send data.
\param[in] handle usart handle to operate.
\param[in] type \ref usart_flush_type_e.
\return error code
*/
int32_t csi_usart_flush(usart_handle_t handle, usart_flush_type_e type)
{
USART_NULL_PARAM_CHK(handle);
dw_usart_priv_t *usart_priv = handle;
dw_usart_reg_t *addr = (dw_usart_reg_t *)(usart_priv->base);
if (type == USART_FLUSH_WRITE) {
while ((!(addr->LSR & DW_LSR_TEMT)));
} else if (type == USART_FLUSH_READ) {
while (addr->LSR & 0x1) {
addr->RBR;
}
} else {
return ERR_USART(DRV_ERROR_PARAMETER);
}
return 0;
}

View file

@ -0,0 +1,997 @@
/*
* Copyright (C) 2017 C-SKY Microsystems Co., Ltd. All rights reserved.
*
* 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 dw_usart.c
* @brief CSI Source File for usart Driver
* @version V1.0
* @date 02. June 2017
******************************************************************************/
#include <csi_config.h>
#include <stdbool.h>
#include <string.h>
#include "drv_usart.h"
#include "dw_usart.h"
#include "soc.h"
#include "csi_core.h"
#define ERR_USART(errno) (CSI_DRV_ERRNO_USART_BASE | errno)
/*
* setting config may be accessed when the USART is not
* busy(USR[0]=0) and the DLAB bit(LCR[7]) is set.
*/
#define WAIT_USART_IDLE(addr)\
do { \
int32_t timecount = 0; \
while ((addr->USR & USR_UART_BUSY) && (timecount < UART_BUSY_TIMEOUT)) {\
timecount++;\
}\
if (timecount >= UART_BUSY_TIMEOUT) {\
return ERR_USART(DRV_ERROR_TIMEOUT);\
} \
} while(0)
#define USART_NULL_PARAM_CHK(para) \
do { \
if (para == NULL) { \
return ERR_USART(DRV_ERROR_PARAMETER); \
} \
} while (0)
typedef struct {
uint32_t base;
uint32_t irq;
usart_event_cb_t cb_event; ///< Event callback
uint32_t rx_total_num;
uint32_t tx_total_num;
uint8_t *rx_buf;
uint8_t *tx_buf;
volatile uint32_t rx_cnt;
volatile uint32_t tx_cnt;
volatile uint32_t tx_busy;
volatile uint32_t rx_busy;
//for get data count
uint32_t last_tx_num;
uint32_t last_rx_num;
int32_t idx;
} dw_usart_priv_t;
extern int32_t target_usart_init(int32_t idx, uint32_t *base, uint32_t *irq);
extern int32_t target_usart_flowctrl_init(int32_t idx, uint32_t flag);
static dw_usart_priv_t usart_instance[CONFIG_USART_NUM];
static const usart_capabilities_t usart_capabilities = {
.asynchronous = 1, /* supports USART (Asynchronous) mode */
.synchronous_master = 0, /* supports Synchronous Master mode */
.synchronous_slave = 0, /* supports Synchronous Slave mode */
.single_wire = 0, /* supports USART Single-wire mode */
.event_tx_complete = 1, /* Transmit completed event */
.event_rx_timeout = 0, /* Signal receive character timeout event */
};
/**
\brief set the baut drate of usart.
\param[in] addr usart base to operate.
\return error code
*/
int32_t csi_usart_config_baudrate(usart_handle_t handle, uint32_t baud)
{
USART_NULL_PARAM_CHK(handle);
dw_usart_priv_t *usart_priv = handle;
dw_usart_reg_t *addr = (dw_usart_reg_t *)(usart_priv->base);
#ifdef CONFIG_CHIP_HOBBIT1_2
uint8_t data[16];
csi_usart_receive_query(handle, data, 16);
#endif
WAIT_USART_IDLE(addr);
/* baudrate=(seriak clock freq)/(16*divisor); algorithm :rounding*/
uint32_t divisor = ((LSP_DEFAULT_FREQ * 10) / baud) >> 4;
if ((divisor % 10) >= 5) {
divisor = (divisor / 10) + 1;
} else {
divisor = divisor / 10;
}
addr->LCR |= LCR_SET_DLAB;
/* DLL and DLH is lower 8-bits and higher 8-bits of divisor.*/
addr->DLL = divisor & 0xff;
addr->DLH = (divisor >> 8) & 0xff;
/*
* The DLAB must be cleared after the baudrate is setted
* to access other registers.
*/
addr->LCR &= (~LCR_SET_DLAB);
return 0;
}
/**
\brief config usart mode.
\param[in] handle usart handle to operate.
\param[in] mode \ref usart_mode_e
\return error code
*/
int32_t csi_usart_config_mode(usart_handle_t handle, usart_mode_e mode)
{
if(mode == USART_MODE_ASYNCHRONOUS) {
return 0;
}
return ERR_USART(USART_ERROR_MODE);
}
/**
\brief config usart parity.
\param[in] handle usart handle to operate.
\param[in] parity \ref usart_parity_e
\return error code
*/
int32_t csi_usart_config_parity(usart_handle_t handle, usart_parity_e parity)
{
USART_NULL_PARAM_CHK(handle);
dw_usart_priv_t *usart_priv = handle;
dw_usart_reg_t *addr = (dw_usart_reg_t *)(usart_priv->base);
WAIT_USART_IDLE(addr);
switch (parity) {
case USART_PARITY_NONE:
/*CLear the PEN bit(LCR[3]) to disable parity.*/
addr->LCR &= (~LCR_PARITY_ENABLE);
break;
case USART_PARITY_ODD:
/* Set PEN and clear EPS(LCR[4]) to set the ODD parity. */
addr->LCR |= LCR_PARITY_ENABLE;
addr->LCR &= LCR_PARITY_ODD;
break;
case USART_PARITY_EVEN:
/* Set PEN and EPS(LCR[4]) to set the EVEN parity.*/
addr->LCR |= LCR_PARITY_ENABLE;
addr->LCR |= LCR_PARITY_EVEN;
break;
default:
return ERR_USART(USART_ERROR_PARITY);
}
return 0;
}
/**
\brief config usart stop bit number.
\param[in] handle usart handle to operate.
\param[in] stopbits \ref usart_stop_bits_e
\return error code
*/
int32_t csi_usart_config_stopbits(usart_handle_t handle, usart_stop_bits_e stopbit)
{
USART_NULL_PARAM_CHK(handle);
dw_usart_priv_t *usart_priv = handle;
dw_usart_reg_t *addr = (dw_usart_reg_t *)(usart_priv->base);
WAIT_USART_IDLE(addr);
switch (stopbit) {
case USART_STOP_BITS_1:
/* Clear the STOP bit to set 1 stop bit*/
addr->LCR &= LCR_STOP_BIT1;
break;
case USART_STOP_BITS_2:
/*
* If the STOP bit is set "1",we'd gotten 1.5 stop
* bits when DLS(LCR[1:0]) is zero, else 2 stop bits.
*/
addr->LCR |= LCR_STOP_BIT2;
break;
default:
return ERR_USART(USART_ERROR_STOP_BITS);
}
return 0;
}
/**
\brief config usart data length.
\param[in] handle usart handle to operate.
\param[in] databits \ref usart_data_bits_e
\return error code
*/
int32_t csi_usart_config_databits(usart_handle_t handle, usart_data_bits_e databits)
{
USART_NULL_PARAM_CHK(handle);
dw_usart_priv_t *usart_priv = handle;
dw_usart_reg_t *addr = (dw_usart_reg_t *)(usart_priv->base);
#ifdef CONFIG_CHIP_HOBBIT1_2
uint8_t data[16];
csi_usart_receive_query(handle, data, 16);
#endif
WAIT_USART_IDLE(addr);
/* The word size decides by the DLS bits(LCR[1:0]), and the
* corresponding relationship between them is:
* DLS word size
* 00 -- 5 bits
* 01 -- 6 bits
* 10 -- 7 bits
* 11 -- 8 bits
*/
switch (databits) {
case USART_DATA_BITS_5:
addr->LCR &= LCR_WORD_SIZE_5;
break;
case USART_DATA_BITS_6:
addr->LCR &= 0xfd;
addr->LCR |= LCR_WORD_SIZE_6;
break;
case USART_DATA_BITS_7:
addr->LCR &= 0xfe;
addr->LCR |= LCR_WORD_SIZE_7;
break;
case USART_DATA_BITS_8:
addr->LCR |= LCR_WORD_SIZE_8;
break;
default:
return ERR_USART(USART_ERROR_DATA_BITS);
}
return 0;
}
/**
\brief get character in query mode.
\param[in] handle usart handle to operate.
\param[in] the pointer to the received character if return 0.
\return error code
*/
int32_t csi_usart_getchar(usart_handle_t handle, uint8_t *ch)
{
dw_usart_priv_t *usart_priv = handle;
dw_usart_reg_t *addr = (dw_usart_reg_t *)(usart_priv->base);
while (!(addr->LSR & LSR_DATA_READY));
*ch = addr->RBR;
return 0;
}
/**
\brief transmit character in query mode.
\param[in] handle usart handle to operate.
\param[in] ch the input character
\return error code
*/
int32_t csi_usart_putchar(usart_handle_t handle, uint8_t ch)
{
dw_usart_priv_t *usart_priv = handle;
dw_usart_reg_t *addr = (dw_usart_reg_t *)(usart_priv->base);
while ((!(addr->LSR & DW_LSR_TRANS_EMPTY)));
addr->THR = ch;
return 0;
}
/**
\brief interrupt service function for transmitter holding register empty.
\param[in] usart_priv usart private to operate.
*/
static void dw_usart_intr_threshold_empty(int32_t idx, dw_usart_priv_t *usart_priv)
{
if (usart_priv->tx_total_num == 0) {
return;
}
dw_usart_reg_t *addr = (dw_usart_reg_t *)(usart_priv->base);
if (usart_priv->tx_cnt >= usart_priv->tx_total_num) {
addr->IER &= (~IER_THRE_INT_ENABLE);
usart_priv->last_tx_num = usart_priv->tx_total_num;
usart_priv->tx_cnt = 0;
usart_priv->tx_busy = 0;
usart_priv->tx_buf = NULL;
usart_priv->tx_total_num = 0;
if (usart_priv->cb_event) {
usart_priv->cb_event(idx, USART_EVENT_SEND_COMPLETE);
}
}else{
uint32_t remain_txdata = usart_priv->tx_total_num - usart_priv->tx_cnt;
uint32_t txdata_num = (remain_txdata > (UART_MAX_FIFO - 1)) ? (UART_MAX_FIFO - 1) : remain_txdata;
uint32_t i = 0u;
for (i = 0; i < txdata_num; i++) {
addr->THR = *((uint8_t *)usart_priv->tx_buf);
usart_priv->tx_cnt++;
usart_priv->tx_buf++;
}
}
}
/**
\brief interrupt service function for receiver data available.
\param[in] usart_priv usart private to operate.
*/
static void dw_usart_intr_recv_data(int32_t idx, dw_usart_priv_t *usart_priv)
{
if ((usart_priv->rx_total_num == 0) || (usart_priv->rx_buf == NULL)) {
usart_priv->cb_event(idx, USART_EVENT_RECEIVED);
return;
}
dw_usart_reg_t *addr = (dw_usart_reg_t *)(usart_priv->base);
uint32_t rxfifo_num = addr->RFL;
uint32_t rxdata_num = (rxfifo_num > usart_priv->rx_total_num) ? usart_priv->rx_total_num : rxfifo_num;
uint32_t i;
for (i = 0; i < rxdata_num; i++) {
*((uint8_t *)usart_priv->rx_buf) = addr->RBR;;
usart_priv->rx_cnt++;
usart_priv->rx_buf++;
}
if (usart_priv->rx_cnt >= usart_priv->rx_total_num) {
usart_priv->last_rx_num = usart_priv->rx_total_num;
usart_priv->rx_cnt = 0;
usart_priv->rx_buf = NULL;
usart_priv->rx_busy = 0;
usart_priv->rx_total_num = 0;
if (usart_priv->cb_event) {
usart_priv->cb_event(idx, USART_EVENT_RECEIVE_COMPLETE);
}
}
}
/**
\brief interrupt service function for receiver line.
\param[in] usart_priv usart private to operate.
*/
static void dw_usart_intr_recv_line(int32_t idx, dw_usart_priv_t *usart_priv)
{
dw_usart_reg_t *addr = (dw_usart_reg_t *)(usart_priv->base);
uint32_t lsr_stat = addr->LSR;
addr->IER &= (~IER_THRE_INT_ENABLE);
while (addr->LSR & 0x1) {
addr->RBR;
}
/** Break Interrupt bit. This is used to indicate the detection of a
* break sequence on the serial input data.
*/
if (lsr_stat & DW_LSR_BI) {
if (usart_priv->cb_event) {
usart_priv->cb_event(idx, USART_EVENT_RX_BREAK);
}
return;
}
/** Framing Error bit. This is used to indicate the occurrence of a
* framing error in the receiver. A framing error occurs when the receiver
* does not detect a valid STOP bit in the received data.
*/
if (lsr_stat & DW_LSR_FE) {
if (usart_priv->cb_event) {
usart_priv->cb_event(idx, USART_EVENT_RX_FRAMING_ERROR);
}
return;
}
/** Framing Error bit. This is used to indicate the occurrence of a
* framing error in the receiver. A framing error occurs when the
* receiver does not detect a valid STOP bit in the received data.
*/
if (lsr_stat & DW_LSR_PE) {
if (usart_priv->cb_event) {
usart_priv->cb_event(idx, USART_EVENT_RX_PARITY_ERROR);
}
return;
}
/** Overrun error bit. This is used to indicate the occurrence of an overrun error.
* This occurs if a new data character was received before the previous data was read.
*/
if (lsr_stat & DW_LSR_OE) {
if (usart_priv->cb_event) {
usart_priv->cb_event(idx, USART_EVENT_RX_OVERFLOW);
}
return;
}
}
/**
\brief interrupt service function for character timeout.
\param[in] usart_priv usart private to operate.
*/
static void dw_usart_intr_char_timeout(int32_t idx, dw_usart_priv_t *usart_priv)
{
if ((usart_priv->rx_total_num != 0) && (usart_priv->rx_buf != NULL)) {
dw_usart_intr_recv_data(idx, usart_priv);
return;
}
if (usart_priv->cb_event) {
usart_priv->cb_event(idx, USART_EVENT_RECEIVED);
} else {
dw_usart_reg_t *addr = (dw_usart_reg_t *)(usart_priv->base);
while (addr->LSR & 0x1) {
addr->RBR;
}
}
}
/**
\brief the interrupt service function.
\param[in] index of usart instance.
*/
void dw_usart_irqhandler(int32_t idx)
{
dw_usart_priv_t *usart_priv = &usart_instance[idx];
dw_usart_reg_t *addr = (dw_usart_reg_t *)(usart_priv->base);
uint8_t intr_state = addr->IIR & 0xf;
switch (intr_state) {
case DW_IIR_THR_EMPTY: /* interrupt source:transmitter holding register empty */
dw_usart_intr_threshold_empty(idx, usart_priv);
break;
case DW_IIR_RECV_DATA: /* interrupt source:receiver data available or receiver fifo trigger level reached */
dw_usart_intr_recv_data(idx, usart_priv);
break;
case DW_IIR_RECV_LINE:
dw_usart_intr_recv_line(idx, usart_priv);
break;
case DW_IIR_CHAR_TIMEOUT:
dw_usart_intr_char_timeout(idx, usart_priv);
break;
default:
break;
}
}
/**
\brief Get driver capabilities.
\param[in] idx usart index
\return \ref usart_capabilities_t
*/
usart_capabilities_t csi_usart_get_capabilities(int32_t idx)
{
if (idx < 0 || idx >= CONFIG_USART_NUM) {
usart_capabilities_t ret;
memset(&ret, 0, sizeof(usart_capabilities_t));
return ret;
}
return usart_capabilities;
}
/**
\brief Initialize USART Interface. 1. Initializes the resources needed for the USART interface 2.registers event callback function
\param[in] idx usart index
\param[in] cb_event Pointer to \ref usart_event_cb_t
\return return usart handle if success
*/
usart_handle_t csi_usart_initialize(int32_t idx, usart_event_cb_t cb_event)
{
uint32_t base = 0u;
uint32_t irq = 0u;
int32_t ret = target_usart_init(idx, &base, &irq);
if (ret < 0 || ret >= CONFIG_USART_NUM) {
return NULL;
}
dw_usart_priv_t *usart_priv = &usart_instance[idx];
usart_priv->base = base;
usart_priv->irq = irq;
usart_priv->cb_event = cb_event;
usart_priv->idx = idx;
dw_usart_reg_t *addr = (dw_usart_reg_t *)(usart_priv->base);
/* FIFO enable */
addr->FCR = DW_FCR_FIFOE | DW_FCR_RT_FIFO_HALF;
/* enable received data available */
addr->IER = IER_RDA_INT_ENABLE | IIR_RECV_LINE_ENABLE;
#ifndef CONFIG_DISABLE_IRQ
csi_vic_enable_irq(usart_priv->irq);
#endif
return usart_priv;
}
/**
\brief De-initialize UART Interface. stops operation and releases the software resources used by the interface
\param[in] handle usart handle to operate.
\return error code
*/
int32_t csi_usart_uninitialize(usart_handle_t handle)
{
USART_NULL_PARAM_CHK(handle);
dw_usart_priv_t *usart_priv = handle;
csi_vic_disable_irq(usart_priv->irq);
usart_priv->cb_event = NULL;
return 0;
}
/**
\brief config usart mode.
\param[in] handle usart handle to operate.
\param[in] baud baud rate
\param[in] mode \ref usart_mode_e
\param[in] parity \ref usart_parity_e
\param[in] stopbits \ref usart_stop_bits_e
\param[in] bits \ref usart_data_bits_e
\return error code
*/
int32_t csi_usart_config(usart_handle_t handle,
uint32_t baud,
usart_mode_e mode,
usart_parity_e parity,
usart_stop_bits_e stopbits,
usart_data_bits_e bits)
{
int32_t ret;
/* control the data_bit of the usart*/
ret = csi_usart_config_baudrate(handle, baud);
if (ret < 0) {
return ret;
}
/* control mode of the usart*/
ret = csi_usart_config_mode(handle, mode);
if (ret < 0) {
return ret;
}
/* control the parity of the usart*/
ret = csi_usart_config_parity(handle, parity);
if (ret < 0) {
return ret;
}
/* control the stopbit of the usart*/
ret = csi_usart_config_stopbits(handle, stopbits);
if (ret < 0) {
return ret;
}
ret = csi_usart_config_databits(handle, bits);
if (ret < 0) {
return ret;
}
return 0;
}
/**
\brief Start sending data to UART transmitter,(received data is ignored).
The function is non-blocking,UART_EVENT_TRANSFER_COMPLETE is signaled when transfer completes.
csi_usart_get_status can indicates if transmission is still in progress or pending
\param[in] handle usart handle to operate.
\param[in] data Pointer to buffer with data to send to UART transmitter. data_type is : uint8_t for 1..8 data bits, uint16_t for 9..16 data bits,uint32_t for 17..32 data bits,
\param[in] num Number of data items to send
\return error code
*/
int32_t csi_usart_send(usart_handle_t handle, const void *data, uint32_t num)
{
USART_NULL_PARAM_CHK(handle);
USART_NULL_PARAM_CHK(data);
if (num == 0) {
return ERR_USART(DRV_ERROR_PARAMETER);
}
dw_usart_priv_t *usart_priv = handle;
//uint8_t *source = NULL;
//source = (uint8_t *)data;
usart_priv->tx_buf = (uint8_t *)data;
usart_priv->tx_total_num = num;
usart_priv->tx_cnt = 0;
usart_priv->tx_busy = 1;
usart_priv->last_tx_num = 0;
dw_usart_reg_t *addr = (dw_usart_reg_t *)(usart_priv->base);
dw_usart_intr_threshold_empty(usart_priv->idx, usart_priv);
/* enable the interrupt*/
addr->IER |= IER_THRE_INT_ENABLE;
return 0;
}
/**
\brief Abort Send data to UART transmitter
\param[in] handle usart handle to operate.
\return error code
*/
int32_t csi_usart_abort_send(usart_handle_t handle)
{
USART_NULL_PARAM_CHK(handle);
dw_usart_priv_t *usart_priv = handle;
dw_usart_reg_t *addr = (dw_usart_reg_t *)(usart_priv->base);
addr->IER &= (~IER_THRE_INT_ENABLE);
usart_priv->tx_cnt = usart_priv->tx_total_num;
usart_priv->tx_cnt = 0;
usart_priv->tx_busy = 0;
usart_priv->tx_buf = NULL;
usart_priv->tx_total_num = 0;
return 0;
}
/**
\brief Start receiving data from UART receiver.
\param[in] handle usart handle to operate.
\param[out] data Pointer to buffer for data to receive from UART receiver
\param[in] num Number of data items to receive
\return error code
*/
int32_t csi_usart_receive(usart_handle_t handle, void *data, uint32_t num)
{
USART_NULL_PARAM_CHK(handle);
USART_NULL_PARAM_CHK(data);
//uint8_t *dest = NULL;
dw_usart_priv_t *usart_priv = handle;
//dest = (uint8_t *)data;
usart_priv->rx_buf = (uint8_t *)data; // Save receive buffer usart
usart_priv->rx_total_num = num; // Save number of data to be received
usart_priv->rx_cnt = 0;
usart_priv->rx_busy = 1;
usart_priv->last_rx_num = 0;
return 0;
}
/**
\brief query data from UART receiver FIFO.
\param[in] handle usart handle to operate.
\param[out] data Pointer to buffer for data to receive from UART receiver
\param[in] num Number of data items to receive
\return receive fifo data num
*/
int32_t csi_usart_receive_query(usart_handle_t handle, void *data, uint32_t num)
{
USART_NULL_PARAM_CHK(handle);
USART_NULL_PARAM_CHK(data);
dw_usart_priv_t *usart_priv = handle;
dw_usart_reg_t *addr = (dw_usart_reg_t *)(usart_priv->base);
int32_t recv_num = 0;
uint8_t *dest = (uint8_t *)data;
while (addr->LSR & 0x1) {
*dest++ = addr->RBR;
recv_num++;
if (recv_num >= num) {
break;
}
}
return recv_num;
}
/**
\brief Abort Receive data from UART receiver
\param[in] handle usart handle to operate.
\return error code
*/
int32_t csi_usart_abort_receive(usart_handle_t handle)
{
USART_NULL_PARAM_CHK(handle);
dw_usart_priv_t *usart_priv = handle;
usart_priv->rx_cnt = usart_priv->rx_total_num;
return 0;
}
/**
\brief Start sending/receiving data to/from UART transmitter/receiver.
\param[in] handle usart handle to operate.
\param[in] data_out Pointer to buffer with data to send to USART transmitter
\param[out] data_in Pointer to buffer for data to receive from USART receiver
\param[in] num Number of data items to transfer
\return error code
*/
int32_t csi_usart_transfer(usart_handle_t handle, const void *data_out, void *data_in, uint32_t num)
{
USART_NULL_PARAM_CHK(handle);
return ERR_USART(DRV_ERROR_UNSUPPORTED);
}
/**
\brief abort sending/receiving data to/from USART transmitter/receiver.
\param[in] handle usart handle to operate.
\return error code
*/
int32_t csi_usart_abort_transfer(usart_handle_t handle)
{
USART_NULL_PARAM_CHK(handle);
return ERR_USART(DRV_ERROR_UNSUPPORTED);
}
/**
\brief Get USART status.
\param[in] handle usart handle to operate.
\return USART status \ref usart_status_t
*/
usart_status_t csi_usart_get_status(usart_handle_t handle)
{
usart_status_t usart_status;
dw_usart_priv_t *usart_priv = handle;
dw_usart_reg_t *addr = (dw_usart_reg_t *)(usart_priv->base);
uint32_t line_status_reg = addr->LSR;
usart_status.tx_busy = usart_priv->tx_busy;
usart_status.rx_busy = usart_priv->rx_busy;
if (line_status_reg & DW_LSR_BI) {
usart_status.rx_break = 1;
}
if (line_status_reg & DW_LSR_FE) {
usart_status.rx_framing_error = 1;
}
if (line_status_reg & DW_LSR_PE) {
usart_status.rx_parity_error = 1;
}
usart_status.tx_enable = 1;
usart_status.rx_enable = 1;
return usart_status;
}
/**
\brief control the transmit.
\param[in] handle usart handle to operate.
\param[in] 1 - enable the transmitter. 0 - disable the transmitter
\return error code
*/
int32_t csi_usart_control_tx(usart_handle_t handle, uint32_t enable)
{
USART_NULL_PARAM_CHK(handle);
return 0;
}
/**
\brief control the receive.
\param[in] handle usart handle to operate.
\param[in] 1 - enable the receiver. 0 - disable the receiver
\return error code
*/
int32_t csi_usart_control_rx(usart_handle_t handle, uint32_t enable)
{
USART_NULL_PARAM_CHK(handle);
return 0;
}
/**
\brief control the break.
\param[in] handle usart handle to operate.
\param[in] 1- Enable continuous Break transmission,0 - disable continuous Break transmission
\return error code
*/
int32_t csi_usart_control_break(usart_handle_t handle, uint32_t enable)
{
USART_NULL_PARAM_CHK(handle);
return ERR_USART(DRV_ERROR_UNSUPPORTED);
}
/**
\brief flush receive/send data.
\param[in] handle usart handle to operate.
\param[in] type \ref usart_flush_type_e.
\return error code
*/
int32_t csi_usart_flush(usart_handle_t handle, usart_flush_type_e type)
{
USART_NULL_PARAM_CHK(handle);
dw_usart_priv_t *usart_priv = handle;
dw_usart_reg_t *addr = (dw_usart_reg_t *)(usart_priv->base);
if (type == USART_FLUSH_WRITE) {
addr->FCR |= DW_FCR_XFIFOR;
while(addr->FCR & DW_FCR_XFIFOR);
} else if (type == USART_FLUSH_READ) {
addr->FCR |= DW_FCR_RFIFOR;
while(addr->FCR & DW_FCR_RFIFOR);
} else {
return ERR_USART(DRV_ERROR_PARAMETER);
}
return 0;
}
/**
\brief set interrupt mode.
\param[in] handle usart handle to operate.
\param[in] type \ref usart_intr_type_e.
\param[in] flag 0-OFF, 1-ON.
\return error code
*/
int32_t csi_usart_set_interrupt(usart_handle_t handle, usart_intr_type_e type, int flag)
{
USART_NULL_PARAM_CHK(handle);
dw_usart_priv_t *usart_priv = handle;
dw_usart_reg_t *addr = (dw_usart_reg_t *)(usart_priv->base);
switch (type)
{
case USART_INTR_WRITE:
if (flag == 0) {
addr->IER &= ~IER_THRE_INT_ENABLE;
}
else {
addr->IER |= IER_THRE_INT_ENABLE;
}
break;
case USART_INTR_READ:
if (flag == 0) {
addr->IER &= ~IER_RDA_INT_ENABLE;
}
else {
addr->IER |= IER_RDA_INT_ENABLE;
}
break;
default:
return ERR_USART(DRV_ERROR_PARAMETER);
}
return 0;
}
/**
\brief Get usart send data count.
\param[in] handle usart handle to operate.
\return number of currently transmitted data bytes
*/
uint32_t csi_usart_get_tx_count(usart_handle_t handle)
{
if (handle == NULL) {
return 0;
}
dw_usart_priv_t *usart_priv = handle;
if(usart_priv->tx_busy)
return usart_priv->tx_cnt;
else
return usart_priv->last_tx_num;
}
/**
\brief Get usart receive data count.
\param[in] handle usart handle to operate.
\return number of currently received data bytes
*/
uint32_t csi_usart_get_rx_count(usart_handle_t handle)
{
if (handle == NULL) {
return 0;
}
dw_usart_priv_t *usart_priv = handle;
if(usart_priv->rx_busy)
return usart_priv->rx_cnt;
else
return usart_priv->last_rx_num;
}
/**
\brief control usart power.
\param[in] handle usart handle to operate.
\param[in] state power state.\ref csi_power_stat_e.
\return error code
*/
int32_t csi_usart_power_control(usart_handle_t handle, csi_power_stat_e state)
{
return ERR_USART(DRV_ERROR_UNSUPPORTED);
}
/**
\brief config usart flow control type.
\param[in] handle usart handle to operate.
\param[in] flowctrl_type flow control type.\ref usart_flowctrl_type_e.
\return error code
*/
int32_t csi_usart_config_flowctrl(usart_handle_t handle,
usart_flowctrl_type_e flowctrl_type)
{
USART_NULL_PARAM_CHK(handle);
dw_usart_priv_t *usart_priv = handle;
dw_usart_reg_t *addr = (dw_usart_reg_t *)(usart_priv->base);
switch (flowctrl_type){
case USART_FLOWCTRL_CTS:
return ERR_USART(DRV_ERROR_UNSUPPORTED);
case USART_FLOWCTRL_RTS:
return ERR_USART(DRV_ERROR_UNSUPPORTED);
case USART_FLOWCTRL_CTS_RTS:
WAIT_USART_IDLE(addr);
addr->MCR |= DW_MCR_AFCE | DW_MCR_RTS;
break;
case USART_FLOWCTRL_NONE:
WAIT_USART_IDLE(addr);
addr->MCR = 0;
break;
default:
return ERR_USART(DRV_ERROR_UNSUPPORTED);
}
return 0;
}
/**
\brief config usart clock Polarity and Phase.
\param[in] handle usart handle to operate.
\param[in] cpol Clock Polarity.\ref usart_cpol_e.
\param[in] cpha Clock Phase.\ref usart_cpha_e.
\return error code
*/
int32_t csi_usart_config_clock(usart_handle_t handle, usart_cpol_e cpol, usart_cpha_e cpha)
{
return ERR_USART(DRV_ERROR_UNSUPPORTED);
}

View file

@ -0,0 +1,253 @@
/*
* Copyright (C) 2017 C-SKY Microsystems Co., Ltd. All rights reserved.
*
* 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 dw_wdt.c
* @brief CSI Source File for WDT Driver
* @version V1.0
* @date 02. June 2017
******************************************************************************/
#include <csi_config.h>
#include <stdio.h>
#include "drv_wdt.h"
#include "dw_wdt.h"
#include "soc.h"
#include "csi_core.h"
#define ERR_WDT(errno) (CSI_DRV_ERRNO_WDT_BASE | errno)
#define SYSTEM_CLOCK_MS (SYSTEM_CLOCK / 1000)
uint32_t timeout_ms[16] = {
(0x10000 << 0)/ SYSTEM_CLOCK_MS,
(0x10000 << 1)/ SYSTEM_CLOCK_MS,
(0x10000 << 2)/ SYSTEM_CLOCK_MS,
(0x10000 << 3)/ SYSTEM_CLOCK_MS,
(0x10000 << 4)/ SYSTEM_CLOCK_MS,
(0x10000 << 5)/ SYSTEM_CLOCK_MS,
(0x10000 << 6)/ SYSTEM_CLOCK_MS,
(0x10000 << 7)/ SYSTEM_CLOCK_MS,
(0x10000 << 8)/ SYSTEM_CLOCK_MS,
(0x10000 << 9)/ SYSTEM_CLOCK_MS,
(0x10000 << 10)/ SYSTEM_CLOCK_MS,
(0x10000 << 11)/ SYSTEM_CLOCK_MS,
(0x10000 << 12)/ SYSTEM_CLOCK_MS,
(0x10000 << 13)/ SYSTEM_CLOCK_MS,
(0x10000 << 14)/ SYSTEM_CLOCK_MS,
((uint32_t)0x10000 << 15)/ SYSTEM_CLOCK_MS
};
#define WDT_NULL_PARAM_CHK(para) \
do { \
if (para == NULL) { \
return ERR_WDT(DRV_ERROR_PARAMETER); \
} \
} while (0)
typedef struct {
uint32_t base;
uint32_t irq;
wdt_event_cb_t cb_event;
} dw_wdt_priv_t;
extern int32_t target_get_wdt_count(void);
extern int32_t target_get_wdt(int32_t idx, uint32_t *base, uint32_t *irq);
static dw_wdt_priv_t wdt_instance[CONFIG_WDT_NUM];
static inline void dw_wdt_enable(dw_wdt_reg_t *addr)
{
uint32_t value = addr->WDT_CR;
value |= 1 << 0;
addr->WDT_CR = value;
}
static inline void dw_wdt_disable(dw_wdt_reg_t *addr)
{
uint32_t value = addr->WDT_CR;
value &= ~(1 << 0);
addr->WDT_CR = value;
}
void dw_wdt_irqhandler(int32_t idx)
{
dw_wdt_priv_t *wdt_priv = &wdt_instance[idx];
dw_wdt_reg_t *addr = (dw_wdt_reg_t *)(wdt_priv->base);
addr->WDT_EOI;
if (wdt_priv->cb_event) {
wdt_priv->cb_event(idx, WDT_EVENT_TIMEOUT);
}
}
/**
\brief Initialize WDT Interface. 1. Initializes the resources needed for the WDT interface 2.registers event callback function
\param[in] idx wdt index
\param[in] cb_event Pointer to \ref wdt_event_cb_t
\return pointer to wdt instance
*/
wdt_handle_t csi_wdt_initialize(int32_t idx, wdt_event_cb_t cb_event)
{
if (idx < 0 || idx >= CONFIG_WDT_NUM) {
return NULL;
}
uint32_t base = 0u;
uint32_t irq = 0u;
int32_t real_idx = target_get_wdt(idx, &base, &irq);
if (real_idx != idx) {
return NULL;
}
dw_wdt_priv_t *wdt_priv = &wdt_instance[idx];
wdt_priv->base = base;
wdt_priv->irq = irq;
wdt_priv->cb_event = cb_event;
csi_vic_enable_irq(wdt_priv->irq);
return (wdt_handle_t)wdt_priv;
}
/**
\brief De-initialize WDT Interface. stops operation and releases the software resources used by the interface
\param[in] instance wdt instance to operate.
\return \ref execution_status
*/
int32_t csi_wdt_uninitialize(wdt_handle_t handle)
{
WDT_NULL_PARAM_CHK(handle);
dw_wdt_priv_t *wdt_priv = handle;
wdt_priv->cb_event = NULL;
csi_vic_disable_irq(wdt_priv->irq);
return 0;
}
/**
\brief Set the WDT value. value = (2^t*0xffff * 10^6 /freq)/10^3(t: 0 ~ 15).
\param[in] handle wdt handle to operate.
\param[in] value the timeout value(ms) \ref:timeout_ms[]
\return \ref execution_status
*/
int32_t csi_wdt_set_timeout(wdt_handle_t handle, uint32_t value)
{
WDT_NULL_PARAM_CHK(handle);
uint32_t i = 0u;
for (i = 0; i <= 15 ; i++) {
if (timeout_ms[i] >= value) {
break;
}
if (i == 15) {
return ERR_WDT(DRV_ERROR_PARAMETER);
}
}
dw_wdt_priv_t *wdt_priv = handle;
dw_wdt_reg_t *addr = (dw_wdt_reg_t *)(wdt_priv->base);
uint32_t config = addr->WDT_CR;
uint32_t en_stat = 0; /*origin wdt enable status*/
if ((config & 0x1) != 0) {
en_stat = 1;
}
config = 0;
addr->WDT_CR = config;
/*before configuration, must disable wdt first*/
dw_wdt_disable(addr);
i += i << 4;
addr->WDT_TORR = i;
if (en_stat == 1) {
dw_wdt_enable(addr);
csi_wdt_restart(handle);
}
return 0;
}
/**
\brief Start the WDT.
\param[in] handle wdt handle to operate.
\return \ref execution_status
*/
int32_t csi_wdt_start(wdt_handle_t handle)
{
WDT_NULL_PARAM_CHK(handle);
dw_wdt_priv_t *wdt_priv = handle;
dw_wdt_reg_t *addr = (dw_wdt_reg_t *)(wdt_priv->base);
dw_wdt_enable(addr);
csi_wdt_restart(handle);
return 0;
}
/**
\brief Stop the WDT.
\param[in] handle wdt handle to operate.
\return \ref execution_status
*/
int32_t csi_wdt_stop(wdt_handle_t handle)
{
WDT_NULL_PARAM_CHK(handle);
return ERR_WDT(DRV_ERROR_UNSUPPORTED);
}
/**
\brief Restart the WDT.
\param[in] handle wdt handle to operate.
\return \ref execution_status
*/
int32_t csi_wdt_restart(wdt_handle_t handle)
{
WDT_NULL_PARAM_CHK(handle);
dw_wdt_priv_t *wdt_priv = handle;
dw_wdt_reg_t *addr = (dw_wdt_reg_t *)(wdt_priv->base);
addr->WDT_CRR = DW_WDT_CRR_RESET;
return 0;
}
/**
\brief Read the WDT Current value.
\param[in] handle wdt handle to operate.
\param[in] value Pointer to the Value.
\return \ref execution_status
*/
int32_t csi_wdt_read_current_value(wdt_handle_t handle, uint32_t *value)
{
WDT_NULL_PARAM_CHK(handle);
WDT_NULL_PARAM_CHK(value);
dw_wdt_priv_t *wdt_priv = handle;
dw_wdt_reg_t *addr = (dw_wdt_reg_t *)(wdt_priv->base);
*value = addr->WDT_CCVR;
return 0;
}

View file

@ -0,0 +1,100 @@
/*
* Copyright (C) 2017 C-SKY Microsystems Co., Ltd. All rights reserved.
*
* 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 ck_sys_freq.c
* @brief header file for setting system frequency.
* @version V1.0
* @date 18. July 2017
******************************************************************************/
#include <stdint.h>
#include <soc.h>
#include <ck_sys_freq.h>
/* FIXME */
#define CK_EFLASH_TRC 0x4003f020
#define CK_EFLASH_TNVS 0x4003f024
#define CK_EFLASH_TPGS 0x4003f028
#define CK_EFLASH_TPROG 0x4003f02c
#define CK_EFLASH_TRCV 0x4003f030
#define CK_EFLASH_TERASE 0x4003f034
void ck_set_sys_freq (clk_gen_t source, clk_val_t val)
{
if (source == IHS_CLK)
return;
uint32_t reg_val;
uint32_t trc_val = 0;
uint32_t stable = 0;
int timeout = 10000;
if (source == EHS_CLK) {
switch (val) {
case CLK_8M:
reg_val = CLK_8M_REG_VAL;
break;
case CLK_16M:
reg_val = CLK_16M_REG_VAL;
break;
case CLK_24M:
reg_val = CLK_24M_REG_VAL;
break;
case CLK_32M:
reg_val = CLK_32M_REG_VAL;
trc_val = TRC_REG_VAL;
break;
case CLK_40M:
*((volatile uint32_t *)CK_EFLASH_TRC) = 0x1;
*((volatile uint32_t *)CK_EFLASH_TNVS) = 0x109;
*((volatile uint32_t *)CK_EFLASH_TPGS) = 0x71;
*((volatile uint32_t *)CK_EFLASH_TPROG) = 0x10c;
*((volatile uint32_t *)CK_EFLASH_TRCV) = 0x89b;
reg_val = CLK_40M_REG_VAL;
trc_val = TRC_REG_VAL;
break;
case CLK_48M:
*((volatile uint32_t *)CK_EFLASH_TRC) = 0x1;
*((volatile uint32_t *)CK_EFLASH_TNVS) = 0x13e;
*((volatile uint32_t *)CK_EFLASH_TPGS) = 0x88;
*((volatile uint32_t *)CK_EFLASH_TPROG) = 0x141;
*((volatile uint32_t *)CK_EFLASH_TRCV) = 0xa56;
reg_val = CLK_48M_REG_VAL;
trc_val = TRC_REG_VAL;
break;
default:
return;
}
*((volatile uint32_t *)PMU_PLL_CTRL) = reg_val;
if (trc_val == TRC_REG_VAL) {
*((volatile uint32_t *)TRC_ADDR) = trc_val;
}
while (timeout--) {
stable = (*(volatile uint32_t *)PMU_CLK_STABLE);
if (stable & 0x00000010)
break;
}
*((volatile uint32_t *)PMU_MCLK_SEL) = MCLK_REG_VAL;
return;
}
return;
}

View file

@ -0,0 +1,51 @@
##
# Copyright (C) 2017 C-SKY Microsystems Co., Ltd. All rights reserved.
#
# 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.
##
INCDIR += -I$(CHIPDIR)/include
INCDIR += -I$(DRIVERDIR)/include
ifneq ($(CONFIG_KERNEL_NONE), y)
ifneq ($(CONFIG_HAVE_VIC), y)
DRIVER_CSRC += $(CHIPDIR)/novic_irq_tbl.c
endif
endif
DRIVER_SSRC += $(CHIPDIR)/startup.S
DRIVER_SSRC += $(CHIPDIR)/vectors.S
DRIVER_CSRC += $(CHIPDIR)/system.c
DRIVER_CSRC += $(CHIPDIR)/isr.c
DRIVER_CSRC += $(CHIPDIR)/lib.c
DRIVER_CSRC += $(CHIPDIR)/devices.c
DRIVER_CSRC += $(CHIPDIR)/pinmux.c
DRIVER_CSRC += $(CHIPDIR)/ck_sys_freq.c
DRIVER_CSRC += $(CHIPDIR)/trap_c.c
DRIVER_CSRC += $(DRIVERDIR)/spi/dw_spi.c
DRIVER_CSRC += $(DRIVERDIR)/usart/dw_usart.c
DRIVER_CSRC += $(DRIVERDIR)/eflash/ck_eflash.c
DRIVER_CSRC += $(DRIVERDIR)/timer/dw_timer.c
DRIVER_CSRC += $(DRIVERDIR)/gpio/dw_gpio.c
DRIVER_CSRC += $(DRIVERDIR)/iic/dw_iic.c
DRIVER_CSRC += $(DRIVERDIR)/rtc/ck_rtc.c
DRIVER_CSRC += $(DRIVERDIR)/wdt/dw_wdt.c
DRIVER_CSRC += $(DRIVERDIR)/pwm/ck_pwm.c
DRIVER_CSRC += $(DRIVERDIR)/dmac/dw_dmac.c
DRIVER_CSRC += $(DRIVERDIR)/adc/ck_adc.c
DRIVER_CSRC += $(DRIVERDIR)/sasc/ck_sasc_v1.c
DRIVER_CSRC += $(DRIVERDIR)/trng/ck_trng.c
DRIVER_CSRC += $(DRIVERDIR)/crc/ck_crc.c
DRIVER_CSRC += $(DRIVERDIR)/aes/ck_aes.c
DRIVER_CSRC += $(DRIVERDIR)/rsa/ck_rsa.c
DRIVER_CSRC += $(DRIVERDIR)/sha/ck_sha_v1.c

View file

@ -0,0 +1,838 @@
/*
* Copyright (C) 2017 C-SKY Microsystems Co., Ltd. All rights reserved.
*
* 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 devices.c
* @brief source file for the devices
* @version V1.0
* @date 24. August 2017
******************************************************************************/
#include "soc.h"
#include <csi_config.h>
#include <drv_usart.h>
#include <drv_timer.h>
#include <drv_rtc.h>
#include <drv_trng.h>
#include <drv_crc.h>
#include <drv_aes.h>
#include <drv_rsa.h>
#include <drv_eflash.h>
#include <drv_spi.h>
#include <drv_adc.h>
#include <drv_gpio.h>
#include <stdio.h>
#include "pin_name.h"
#include "pinmux.h"
#define readl(addr) \
({ unsigned int __v = (*(volatile unsigned int *) (addr)); __v; })
#define writel(b,addr) (void)((*(volatile unsigned int *) (addr)) = (b))
struct {
uint32_t base;
uint32_t irq;
uint32_t pin_num;
port_name_t port;
}
const sg_gpio_config[CONFIG_GPIO_NUM] = {
{CSKY_GPIO0_BASE, GPIOA_IRQn, 28, PORTA},
{CSKY_GPIO1_BASE, GPIOB_IRQn, 4, PORTB},
};
typedef struct {
int32_t gpio_pin;
uint32_t cfg_idx; //idx of sg_gpio_config[]
} gpio_pin_map_t;
const static gpio_pin_map_t s_gpio_pin_map[] = {
{PA0_TRIG0_ACMP1P_TCK, 0},
{PA1_TRIG1_ACMP1N_TMS, 0},
{PA2_TXD0_SPI0MISO, 0},
{PA3_RXD0_SPI0MOSI, 0},
{PA4_CTS0_PWM0_SPI0SCK_TRIG0, 0},
{PA5_RTS0_PWM1_SPI0SSN_TRIG1, 0},
{PB0_SCL0_PWM2_I2SMCLK, 1},
{PB1_SDA0_PWM3_I2SSCK, 1},
{PB2_SPI0SCK_PWM4_I2SWS, 1},
{PB3_SPI0MISO_PWM5_I2SSD, 1},
{PA6_SPI0MOSI_PWM6_SCL0, 0},
{PA7_SPI0SSN_PWM7_SDA0, 0},
{PA8_WKUP_ADC0_ACMP0P, 0},
{PA9_BOOT_ADC1_PWMFAULT, 0},
{PA10_ADC2_TXD0, 0},
{PA11_ACMP0N_ADC3_RXD0, 0},
{PA12_PWM8_TCK_ADC4, 0},
{PA13_PWM9_TMS_ADC5, 0},
{PA14_PWM10_ADC6, 0},
{PA15_PWM11_ADC7, 0},
{PA16_RXD1_ADC8, 0},
{PA17_TXD1_ADC9, 0},
{PA18_SPI1SSN0_ACMP0O, 0},
{PA19_SPI1SSN1_ACMP1O, 0},
{PA20_SPI1SSN2_TRIG0_RXD1, 0},
{PA21_SPI1SCK_TRIG1_TXD1, 0},
{PA22_SPI1MISO_PWM0_ADC10, 0},
{PA23_SPI1MOSI_PWM1_ADC11, 0},
{PA24_TXD2_I2SMCLK_SPI1SSN0, 0},
{PA25_RXD2_I2SSCK_SPI1SSN1, 0},
{PA26_CTS2_I2SWS_ADC12, 0},
{PA27_RTS2_I2SSD_ADC13, 0}
};
int32_t target_gpio_port_init(port_name_t port, uint32_t *base, uint32_t *irq, uint32_t *pin_num)
{
int i;
for (i = 0; i < CONFIG_GPIO_NUM; i++) {
if (sg_gpio_config[i].port == port) {
*base = sg_gpio_config[i].base;
*irq = sg_gpio_config[i].irq;
*pin_num = sg_gpio_config[i].pin_num;
return i;
}
}
return -1;
}
/**
\param[in] instance idx, must not exceed return value of target_get_gpio_count()
\brief get gpio instance.
\return pointer to gpio instance
*/
int32_t target_gpio_pin_init(int32_t gpio_pin, uint32_t *port_idx)
{
uint32_t idx;
for (idx = 0; idx < sizeof(s_gpio_pin_map) / sizeof(gpio_pin_map_t); idx++) {
if (s_gpio_pin_map[idx].gpio_pin == gpio_pin) {
*port_idx = s_gpio_pin_map[idx].cfg_idx;
/*pinmux*/
pin_mux(s_gpio_pin_map[idx].gpio_pin, 0xff);
if (idx >= 10) {
return idx - 4;
} else if (idx >= 6) {
return idx - 6;
} else {
return idx;
}
}
}
return -1;
}
struct {
uint32_t base;
uint32_t irq;
}
const sg_timer_config[CONFIG_TIMER_NUM] = {
{CSKY_TIM0_BASE, TIMA0_IRQn},
{CSKY_TIM0_BASE + 0x14, TIMA1_IRQn},
{CSKY_TIM1_BASE, TIMB0_IRQn},
{CSKY_TIM1_BASE + 0x14, TIMB1_IRQn}
};
int32_t target_get_timer_count(void)
{
return CONFIG_TIMER_NUM;
}
int32_t target_get_timer(int32_t idx, uint32_t *base, uint32_t *irq)
{
if (idx >= target_get_timer_count()) {
return NULL;
}
*base = sg_timer_config[idx].base;
*irq = sg_timer_config[idx].irq;
return idx;
}
#undef CSKY_PMU_BASE
#define CSKY_PMU_BASE 0x40002000
#define BIT1 (0x1)
struct {
uint32_t base;
uint32_t irq;
}
const sg_rtc_config[CONFIG_RTC_NUM] = {
{CSKY_RTC0_BASE, RTC_IRQn},
{CSKY_RTC1_BASE, RTC1_IRQn}
};
int32_t target_get_rtc_count(void)
{
return CONFIG_RTC_NUM;
}
int32_t target_get_rtc(int32_t idx, uint32_t *base, uint32_t *irq)
{
unsigned int value;
if (idx >= target_get_rtc_count()) {
return NULL;
}
value = readl(CSKY_PMU_BASE);
value &= ~BIT1;
writel(value, CSKY_PMU_BASE);
*base = sg_rtc_config[idx].base;
*irq = sg_rtc_config[idx].irq;
return idx;
}
struct {
uint32_t base;
}
const sg_trng_config[CONFIG_TRNG_NUM] = {
{CSKY_TRNG_BASE}
};
/**
\brief get trng instance count.
\return trng instance count
*/
int32_t target_get_trng_count(void)
{
return CONFIG_TRNG_NUM;
}
/**
\param[in] instance idx, must not exceed return value of target_get_trng_count()
\brief get trng instance.
\return pointer to trng instance
*/
int32_t target_get_trng(int32_t idx, uint32_t *base)
{
if (idx >= target_get_trng_count()) {
return NULL;
}
*base = sg_trng_config[idx].base;
return idx;
}
struct {
uint32_t base;
}
const sg_crc_config[CONFIG_CRC_NUM] = {
{CSKY_CRC_BASE}
};
/**
\brief get crc instance count.
\return crc instance count
*/
int32_t target_get_crc_count(void)
{
return CONFIG_CRC_NUM;
}
/**
\param[in] instance idx, must not exceed return value of target_get_crc_count()
\brief get crc instance.
\return pointer to crc instance
*/
int32_t target_get_crc(int32_t idx, uint32_t *base)
{
if (idx >= target_get_crc_count()) {
return NULL;
}
*base = sg_crc_config[idx].base;
return idx;
}
struct {
uint32_t base;
uint32_t irq;
}
const sg_usart_config[CONFIG_USART_NUM] = {
{CSKY_UART0_BASE, UART0_IRQn},
{CSKY_UART1_BASE, UART1_IRQn},
{CSKY_UART2_BASE, UART2_IRQn},
};
typedef struct {
int32_t tx;
int32_t rx;
int32_t cts;
int32_t rts;
uint16_t cfg_idx; //idx of sg_usart_config[]
uint16_t function;
} usart_pin_map_t;
const static usart_pin_map_t s_usart_pin_map[] = {
{
PA10_ADC2_TXD0,
PA11_ACMP0N_ADC3_RXD0,
-1,
-1,
0,
2
},
{
PA17_TXD1_ADC9,
PA16_RXD1_ADC8,
-1,
-1,
1,
0
},
{
PA24_TXD2_I2SMCLK_SPI1SSN0,
PA25_RXD2_I2SSCK_SPI1SSN1,
PA26_CTS2_I2SWS_ADC12,
PA27_RTS2_I2SSD_ADC13,
2,
0
},
};
/**
\param[in] instance idx, must not exceed return value of target_get_usart_count()
\brief get usart instance.
\return pointer to usart instance
*/
int32_t target_usart_init(int32_t idx, uint32_t *base, uint32_t *irq)
{
if (idx >= sizeof(s_usart_pin_map) / sizeof(usart_pin_map_t)) {
return -1;
}
*base = sg_usart_config[s_usart_pin_map[idx].cfg_idx].base;
*irq = sg_usart_config[s_usart_pin_map[idx].cfg_idx].irq;
/*pinmux*/
pin_mux(s_usart_pin_map[idx].tx, s_usart_pin_map[idx].function);
pin_mux(s_usart_pin_map[idx].rx, s_usart_pin_map[idx].function);
return s_usart_pin_map[idx].cfg_idx;
}
/**
\brief control usart flow.
\param[in] tx_flow The TX flow pin name
\param[in] rx_flow The RX flow pin name
\param[in] flag 0-disable, 1-enable.
\return 0 if setting ready ,negative for error code
*/
int32_t target_usart_flowctrl_init(int32_t idx, uint32_t flag)
{
if (idx >= sizeof(s_usart_pin_map) / sizeof(usart_pin_map_t)) {
return -1;
}
if (flag) {
pin_mux(s_usart_pin_map[idx].rts, s_usart_pin_map[idx].function);
pin_mux(s_usart_pin_map[idx].cts, s_usart_pin_map[idx].function);
} else if (flag == 0) {
pin_mux(s_usart_pin_map[idx].cts, 0xff);
pin_mux(s_usart_pin_map[idx].rts, 0xff);
} else {
return -1;
}
return 0;
}
struct {
uint32_t base;
uint32_t irq;
}
const sg_spi_config[CONFIG_SPI_NUM] = {
{CSKY_SPI0_BASE, SPI0_IRQn},
{CSKY_SPI1_BASE, SPI1_IRQn}
};
typedef struct {
int32_t mosi;
int32_t miso;
int32_t sclk;
int32_t ssel;
uint32_t cfg_idx; //idx of sg_iic_config[]
uint16_t function;
} spi_pin_map_t;
const static spi_pin_map_t s_spi_pin_map[] = {
{
PB3_SPI0MISO_PWM5_I2SSD,
PA6_SPI0MOSI_PWM6_SCL0,
PB2_SPI0SCK_PWM4_I2SWS,
PA7_SPI0SSN_PWM7_SDA0,
0,
0
},
{
PA22_SPI1MISO_PWM0_ADC10,
PA23_SPI1MOSI_PWM1_ADC11,
PA21_SPI1SCK_TRIG1_TXD1,
PA18_SPI1SSN0_ACMP0O,
1,
0
}
};
/**
\param[in] instance idx, must not exceed return value of target_get_spi_count()
\brief get spi instance.
\return pointer to spi instance
*/
int32_t target_spi_init(int32_t idx, uint32_t *base, uint32_t *irq, uint32_t *ssel)
{
if (idx >= sizeof(s_spi_pin_map) / sizeof(spi_pin_map_t)) {
return -1;
}
*base = sg_spi_config[s_spi_pin_map[idx].cfg_idx].base;
*irq = sg_spi_config[s_spi_pin_map[idx].cfg_idx].irq;
*ssel = s_spi_pin_map[idx].ssel;
/*pinmux*/
pin_mux(s_spi_pin_map[idx].mosi, s_spi_pin_map[idx].function);
pin_mux(s_spi_pin_map[idx].miso, s_spi_pin_map[idx].function);
pin_mux(s_spi_pin_map[idx].sclk, s_spi_pin_map[idx].function);
pin_mux(s_spi_pin_map[idx].ssel, s_spi_pin_map[idx].function);
return s_spi_pin_map[idx].cfg_idx;
}
struct {
uint32_t base;
uint32_t irq;
}
const sg_aes_config[CONFIG_AES_NUM] = {
{CSKY_AES_BASE, AES_IRQn}
};
/**
\brief get aes instance count.
\return aes instance count
*/
int32_t target_get_aes_count(void)
{
return CONFIG_AES_NUM;
}
/**
\param[in] instance idx, must not exceed return value of target_get_aes_count()
\brief get aes instance.
\return pointer to aes instance
*/
int32_t target_get_aes(int32_t idx, uint32_t *base, uint32_t *irq)
{
if (idx >= target_get_aes_count()) {
return NULL;
}
*base = sg_aes_config[idx].base;
*irq = sg_aes_config[idx].irq;
return idx;
}
struct {
uint32_t base;
uint32_t irq;
}
const sg_rsa_config[CONFIG_RSA_NUM] = {
{CSKY_RSA_BASE, RSA_IRQn}
};
/**
\brief get rsa instance count.
\return rsa instance count
*/
int32_t target_get_rsa_count(void)
{
return CONFIG_RSA_NUM;
}
/**
\param[in] instance idx, must not exceed return value of target_get_rsa_count()
\brief get rsa instance.
\return pointer to rsa instance
*/
int32_t target_get_rsa(int32_t idx, uint32_t *base, uint32_t *irq)
{
if (idx >= target_get_rsa_count()) {
return NULL;
}
*base = sg_rsa_config[idx].base;
*irq = sg_rsa_config[idx].irq;
return idx;
}
struct {
uint32_t base;
eflash_info_t info;
}
const sg_eflash_config[CONFIG_EFLASH_NUM] = {
{CSKY_EFLASH_CONTROL_BASE, {0x10000000, 0x1003f800, 0x1fc}}
};
/**
\brief get eflash instance count.
\return eflash instance count
*/
int32_t target_get_eflash_count(void)
{
return CONFIG_EFLASH_NUM;
}
/**
\param[in] instance idx, must not exceed return value of target_get_eflash_count()
\brief get eflash instance.
\return pointer to eflash instance
*/
int32_t target_get_eflash(int32_t idx, uint32_t *base, eflash_info_t *info)
{
if (idx >= target_get_eflash_count()) {
return NULL;
}
*base = sg_eflash_config[idx].base;
info->start = sg_eflash_config[idx].info.start;
info->end = sg_eflash_config[idx].info.end;
info->sector_count = sg_eflash_config[idx].info.sector_count;
return idx;
}
struct {
uint32_t base;
uint32_t irq;
}
const sg_wdt_config[CONFIG_WDT_NUM] = {
{CSKY_WDT_BASE, WDT_IRQn}
};
int32_t target_get_wdt_count(void)
{
return CONFIG_WDT_NUM;
}
int32_t target_get_wdt(int32_t idx, uint32_t *base, uint32_t *irq)
{
if (idx >= target_get_wdt_count()) {
return NULL;
}
*base = sg_wdt_config[idx].base;
*irq = sg_wdt_config[idx].irq;
return idx;
}
struct {
uint32_t base;
uint32_t irq;
}
const sg_dmac_config[CONFIG_DMAC_NUM] = {
{CSKY_DMAC0_BASE, SEU_DMAC_IRQn},
{CSKY_DMAC1_BASE, NONSEU_DMAC_IRQn}
};
int32_t target_get_dmac_count(void)
{
return CONFIG_DMAC_NUM;
}
int32_t target_get_dmac(int32_t idx, uint32_t *base, uint32_t *irq)
{
if (idx >= target_get_dmac_count()) {
return NULL;
}
*base = sg_dmac_config[idx].base;
*irq = sg_dmac_config[idx].irq;
return idx;
}
struct {
uint32_t base;
uint32_t irq;
}
const sg_iic_config[CONFIG_IIC_NUM] = {
{CSKY_I2C0_BASE, I2C0_IRQn},
{CSKY_I2C1_BASE, I2C1_IRQn}
};
typedef struct {
int32_t scl;
int32_t sda;
uint16_t cfg_idx; //idx of sg_iic_config[]
uint16_t function;
} iic_pin_map_t;
const static iic_pin_map_t s_iic_pin_map[] = {
{
PA6_SPI0MOSI_PWM6_SCL0,
PA7_SPI0SSN_PWM7_SDA0,
0,
2
},
{
PC0_SCL1_CTS1_PWM10_ADC14,
PC1_SDA1_RTS1_PWM11_ADC15,
1,
0
}
};
/**
\param[in] instance idx, must not exceed return value of target_get_iic_count()
\brief get iic instance.
\return pointer to iic instance
*/
int32_t target_iic_init(int32_t idx, uint32_t *base, uint32_t *irq)
{
if (idx >= sizeof(s_iic_pin_map) / sizeof(iic_pin_map_t)) {
return -1;
}
*base = sg_iic_config[s_iic_pin_map[idx].cfg_idx].base;
*irq = sg_iic_config[s_iic_pin_map[idx].cfg_idx].irq;
/*pinmux*/
pin_mux(s_iic_pin_map[idx].scl, s_iic_pin_map[idx].function);
pin_mux(s_iic_pin_map[idx].sda, s_iic_pin_map[idx].function);
return s_iic_pin_map[idx].cfg_idx;
}
struct {
uint32_t base;
uint32_t irq;
}
const sg_pwm_config[CONFIG_PWM_NUM] = {
{CSKY_PWM_BASE, PWM_IRQn},
};
typedef struct {
int32_t pwm_pin;
uint32_t cfg_idx; //idx of sg_pwm_config[]
uint32_t ch_num;
uint16_t function;
} pwm_pin_map_t;
const static pwm_pin_map_t s_pwm_pin_map[] = {
{PA4_CTS0_PWM0_SPI0SCK_TRIG0, 0, 0, 1},
{PA5_RTS0_PWM1_SPI0SSN_TRIG1, 0, 0, 1},
{PB0_SCL0_PWM2_I2SMCLK, 0, 1, 1},
{PB1_SDA0_PWM3_I2SSCK, 0, 1, 1},
{PB2_SPI0SCK_PWM4_I2SWS, 0, 2, 1},
{PB3_SPI0MISO_PWM5_I2SSD, 0, 2, 1},
{PA6_SPI0MOSI_PWM6_SCL0, 0, 3, 1},
{PA7_SPI0SSN_PWM7_SDA0, 0, 3, 1},
{PA12_PWM8_TCK_ADC4, 0, 4, 0},
{PA13_PWM9_TMS_ADC5, 0, 4, 0},
{PA14_PWM10_ADC6, 0, 5, 0},
{PA15_PWM11_ADC7, 0, 5, 0},
{PA22_SPI1MISO_PWM0_ADC10, 0, 0, 1},
{PA23_SPI1MOSI_PWM1_ADC11, 0, 0, 1},
{PC0_SCL1_CTS1_PWM10_ADC14, 0, 5, 2},
{PC1_SDA1_RTS1_PWM11_ADC15, 0, 5, 2}
};
/**
\param[in] instance idx, must not exceed return value of target_get_pwm_count()
\brief get pwm instance.
\return pointer to pwm instance
*/
int32_t target_pwm_init(int32_t pwm_pin, uint32_t *ch_num, uint32_t *base, uint32_t *irq)
{
uint32_t idx;
for (idx = 0; idx < sizeof(s_pwm_pin_map) / sizeof(pwm_pin_map_t); idx++) {
if (s_pwm_pin_map[idx].pwm_pin == pwm_pin) {
*base = sg_pwm_config[s_pwm_pin_map[idx].cfg_idx].base;
*irq = sg_pwm_config[s_pwm_pin_map[idx].cfg_idx].irq;
*ch_num = s_pwm_pin_map[idx].ch_num;
/*pinmux*/
pin_mux(s_pwm_pin_map[idx].pwm_pin, s_pwm_pin_map[idx].function);
return s_pwm_pin_map[idx].cfg_idx;
}
}
return -1;
}
struct {
uint32_t base;
uint32_t irq;
}
const sg_sha_config[CONFIG_SHA_NUM] = {
{CSKY_SHA_BASE, SHA_IRQn}
};
/**
\brief get sha instance count.
\return sha instance count
*/
int32_t target_get_sha_count(void)
{
return CONFIG_SHA_NUM;
}
/**
\param[in] instance idx, must not exceed return value of target_get_sha_count()
\brief get sha instance.
\return pointer to sha instance
*/
int32_t target_get_sha(int32_t idx, uint32_t *base, uint32_t *irq)
{
if (idx >= target_get_sha_count()) {
return NULL;
}
*base = sg_sha_config[idx].base;
*irq = sg_sha_config[idx].irq;
return idx;
}
struct {
uint32_t base;
uint32_t irq;
}
const sg_adc_config[CONFIG_ADC_NUM] = {
{CSKY_ADC_CTL_BASE, ADC_IRQn}
};
typedef struct {
int32_t port;
uint16_t function;
} adc_pin_map_t;
const static adc_pin_map_t s_adc_pin_map[] = {
{
PA8_WKUP_ADC0_ACMP0P,
1
},
{
PA9_BOOT_ADC1_PWMFAULT,
1
},
{
PA10_ADC2_TXD0,
1
},
{
PA11_ACMP0N_ADC3_RXD0,
1
},
{
PA12_PWM8_TCK_ADC4,
2
},
{
PA13_PWM9_TMS_ADC5,
2
},
{
PA14_PWM10_ADC6,
1
},
{
PA15_PWM11_ADC7,
1
},
{
PA16_RXD1_ADC8,
1
},
{
PA17_TXD1_ADC9,
1
},
{
PA22_SPI1MISO_PWM0_ADC10,
2
},
{
PA23_SPI1MOSI_PWM1_ADC11,
2
},
{
PA26_CTS2_I2SWS_ADC12,
2
},
{
PA27_RTS2_I2SSD_ADC13,
2
},
{
PC0_SCL1_CTS1_PWM10_ADC14,
3
},
{
PC1_SDA1_RTS1_PWM11_ADC15,
3
}
};
/**
\param[in] initialize adc channel;
\brief get instance.
\return 0 - success, (-1) - fail.
*/
int32_t target_adc_init(int32_t channel)
{
int32_t ret;
if ((channel >= 0) && (channel <= 15)) {
ret = pin_mux(s_adc_pin_map[channel].port, s_adc_pin_map[channel].function);
if (ret == 0) {
return 0;
} else {
return -1;
}
} else {
return -1;
}
return -1;
}
/**
\brief get adc instance count.
\return adc instance count
*/
int32_t target_get_adc_count(void)
{
return CONFIG_ADC_NUM;
}
/**
\param[in] instance idx, must not exceed return value of target_get_adc_count()
\brief get sha instance.
\return pointer to adc instance
*/
int32_t target_get_adc(int32_t idx, uint32_t *base, uint32_t *irq)
{
if (idx >= target_get_adc_count()) {
return NULL;
}
*base = sg_adc_config[idx].base;
*irq = sg_adc_config[idx].irq;
return idx;
}

View file

@ -0,0 +1,68 @@
/*
* Copyright (C) 2017 C-SKY Microsystems Co., Ltd. All rights reserved.
*
* 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 ck_sys_freq.h
* @brief header file for setting system frequency.
* @version V1.0
* @date 18. July 2017
******************************************************************************/
#ifndef _CK_SYS_FREQ_H_
#define _CK_SYS_FREQ_H_
#include <stdint.h>
#include "soc.h"
#define PMU_MCLK_SEL (CSKY_CLKGEN_BASE + 0x4)
#define MCLK_REG_VAL 0x8UL
#define PMU_CLK_STABLE (CSKY_CLKGEN_BASE + 0x18)
#define PMU_PLL_CTRL (CSKY_CLKGEN_BASE + 0x2c)
#define TRC_ADDR (CSKY_OTP_BASE + 0x20)
#define TRC_REG_VAL 0x1UL
#define EXTERNAL_CLK_SOURCE 0x8UL
#define EXTERNAL_CLK_16M (EXTERNAL_CLK_SOURCE * 2)
#define EXTERNAL_CLK_24M (EXTERNAL_CLK_SOURCE * 3)
#define EXTERNAL_CLK_32M (EXTERNAL_CLK_SOURCE * 4)
#define EXTERNAL_CLK_40M (EXTERNAL_CLK_SOURCE * 5)
#define EXTERNAL_CLK_48M (EXTERNAL_CLK_SOURCE * 6)
#define CLK_8M_REG_VAL 0xc0202UL
#define CLK_16M_REG_VAL 0xc0204UL
#define CLK_24M_REG_VAL 0xc0206UL
#define CLK_32M_REG_VAL 0xc0208UL
#define CLK_40M_REG_VAL 0xc020aUL
#define CLK_48M_REG_VAL 0xc020cUL
typedef enum {
IHS_CLK = 0, //internal high speed clock
EHS_CLK = 1 //external high speed clock
} clk_gen_t;
typedef enum {
CLK_8M = 0,
CLK_16M = 1,
CLK_24M = 2,
CLK_32M = 3,
CLK_40M = 4,
CLK_48M = 5
} clk_val_t;
void ck_set_sys_freq (clk_gen_t source, clk_val_t val);
#endif /* _CK_SYS_FREQ_H_ */

View file

@ -0,0 +1,142 @@
/*
* Copyright (C) 2017 C-SKY Microsystems Co., Ltd. All rights reserved.
*
* 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 Header File for register bits operation
* @version V1.0
* @date 20. October 2017
******************************************************************************/
#ifndef _IO_H_
#define _IO_H_
#define BIT(n) (1UL << (n))
#define BIT_MASK(n) (BIT(n) - 1)
/* bit field operate*/
#define REG64(addr) (*(volatile uint64_t *)(addr))
#define REG32(addr) (*(volatile uint32_t *)(addr))
#define REG16(addr) (*(volatile uint16_t *)(addr))
#define REG8(addr) (*(volatile uint8_t *)(addr))
/** insert value to some field in reg,other field is set to 0(the Field MaKe macro) */
#define HAL_FMK(PER_REG_FIELD, val) \
(((val) << PER_REG_FIELD##_SHIFT) & PER_REG_FIELD##_MASK)
/* get value of some field in reg(the Field EXTract macro) */
#define HAL_FEXT(reg, PER_REG_FIELD) \
(((reg) & PER_REG_FIELD##_MASK) >> PER_REG_FIELD##_SHIFT)
/* insert value to some field in reg,other field don't change(the Field INSert macro) */
#define HAL_FINS(reg, PER_REG_FIELD, val) \
((reg) = ((reg) & ~PER_REG_FIELD##_MASK) \
| HAL_FMK(PER_REG_FIELD, val))
/* bit operate */
/* set one value to 1,other bit don't change*/
#define HAL_BIT_SET(reg, bit) ((reg) = ((reg) | (1u << (bit))))
/* set one value to 0,other bit don't change*/
#define HAL_BIT_CLR(reg, bit) ((reg) = ((reg) & (~(1u << (bit)))))
/* get value of one bit(0/1) */
#define HAL_GET_BIT_VAL(reg, bit) (((reg)>> (bit)) & 1u)
/*judge one bit is 1 or not */
#define HAL_IS_BIT_SET(reg, pos) (((reg) & (1u << (pos))) != 0x0u)
/* judge one bit is 0 or not */
#define HAL_IS_BIT_CLR(reg, pos) (((reg) & (1u << (pos))) == 0x0u)
/* set one value to bit,other bit don't change*/
#define HAL_BIT_INSR(reg, bit, val) \
((reg) = (((reg) & (~(1u << (bit)))) | (((val) & 1u) << (bit))))
static inline uint8_t getreg8(volatile uint32_t *addr)
{
return *(volatile uint8_t *)addr;
}
static inline void putreg8(uint8_t val, volatile uint32_t *addr)
{
*(volatile uint8_t *)addr = val;
}
static inline uint32_t getreg32(volatile uint32_t *addr)
{
return *(volatile uint32_t *)addr;
}
static inline void putreg32(uint32_t val, volatile uint32_t *addr)
{
*(volatile uint32_t *)addr = val;
}
static inline uint32_t inl(uint32_t addr)
{
return *(volatile uint32_t *)addr;
}
static inline void outl(uint32_t val, uint32_t addr)
{
*(volatile uint32_t *)addr = val;
}
static inline void set_bit(int nr, volatile uint32_t *addr)
{
*addr |= BIT(nr);
}
static inline void clear_bit(int nr, volatile uint32_t *addr)
{
*addr &= ~BIT(nr);
}
static inline void write_bit(int nr, volatile uint32_t *addr, int val)
{
uint32_t temp = *addr;
temp = val ? (temp | BIT(nr)) : (temp & ~BIT(nr));
*addr = temp;
}
static inline int test_bit(int nr, const volatile uint32_t *addr)
{
return (*addr >> nr) & 0x1;
}
static inline int read_bits(int width, int nr, const volatile uint32_t *addr)
{
return (*addr >> nr) & BIT_MASK(width);
}
static inline void write_bits(int width, int nr, volatile uint32_t *addr, int val)
{
uint32_t temp = *addr;
temp &= ~(BIT_MASK(width) << nr);
temp |= (val << nr);
*addr = temp;
}
#endif /* _IO_H_ */

View file

@ -0,0 +1,83 @@
/*
* Copyright (C) 2017 C-SKY Microsystems Co., Ltd. All rights reserved.
*
* 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 pin_name.h
* @brief header file for the pin_name
* @version V1.0
* @date 23. August 2017
******************************************************************************/
#ifndef _PINNAMES_H
#define _PINNAMES_H
#ifdef __cplusplus
extern "C" {
#endif
typedef enum {
PA0_TRIG0_ACMP1P_TCK = 0,
PA1_TRIG1_ACMP1N_TMS,
PA2_TXD0_SPI0MISO,
PA3_RXD0_SPI0MOSI,
PA4_CTS0_PWM0_SPI0SCK_TRIG0,
PA5_RTS0_PWM1_SPI0SSN_TRIG1,
PB0_SCL0_PWM2_I2SMCLK,
PB1_SDA0_PWM3_I2SSCK,
PB2_SPI0SCK_PWM4_I2SWS,
PB3_SPI0MISO_PWM5_I2SSD,
PA6_SPI0MOSI_PWM6_SCL0,
PA7_SPI0SSN_PWM7_SDA0,
PA8_WKUP_ADC0_ACMP0P,
PA9_BOOT_ADC1_PWMFAULT,
PA10_ADC2_TXD0,
PA11_ACMP0N_ADC3_RXD0,
PA12_PWM8_TCK_ADC4,
PA13_PWM9_TMS_ADC5,
PA14_PWM10_ADC6,
PA15_PWM11_ADC7,
PA16_RXD1_ADC8,
PA17_TXD1_ADC9,
PA18_SPI1SSN0_ACMP0O,
PA19_SPI1SSN1_ACMP1O,
PA20_SPI1SSN2_TRIG0_RXD1,
PA21_SPI1SCK_TRIG1_TXD1,
PA22_SPI1MISO_PWM0_ADC10,
PA23_SPI1MOSI_PWM1_ADC11,
PA24_TXD2_I2SMCLK_SPI1SSN0,
PA25_RXD2_I2SSCK_SPI1SSN1,
PA26_CTS2_I2SWS_ADC12,
PA27_RTS2_I2SSD_ADC13,
PC0_SCL1_CTS1_PWM10_ADC14,
PC1_SDA1_RTS1_PWM11_ADC15,
}
pin_name_t;
typedef enum {
PORTA = 0,
PORTB = 1,
} port_name_t;
#ifdef __cplusplus
}
#endif
#endif

View file

@ -0,0 +1,122 @@
/*
* Copyright (C) 2017 C-SKY Microsystems Co., Ltd. All rights reserved.
*
* 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 pinmux.h
* @brief Header file for the pinmux
* @version V1.0
* @date 23. August 2017
******************************************************************************/
#ifndef HOBBIT1_2_PINMUX_H
#define HOBBIT1_2_PINMUX_H
#include <stdint.h>
#include "pin_name.h"
void hobbit_ioreuse_initial(void);
int32_t pin_mux(pin_name_t pin, uint16_t function);
/*IOMUX0L function definition */
/* IOMUX0H function definition */
#define PA16_UART1_RX 0x00010000
#define PA17_UART1_TX 0x00020000
#define PA20_UART1_RX 0x00020000
#define PA21_UART1_TX 0x00080000
//use for spi eth
#define PA3_SPI0MOSI 0x00000080
#define PA2_SPI0MISO 0x00000020
#define PA4_SPI0SCK 0x00000200
#define PA5_SPI0SSN 0x00000800
#define PA23_SPI1MOSI 0x00800000
#define PA22_SPI1MISO 0x00400000
#define PA21_SPI1SCK 0x00200000
#define PA18_SPI1SSN0 0x00040000
/* IOMUX1L function definition */
/* flag as identification */
#define GPIO_SET_BIT0 0x00000001
#define GPIO_SET_BIT1 0x00000002
#define GPIO_SET_BIT2 0x00000004
#define GPIO_SET_BIT3 0x00000008
#define GPIO_SET_BIT4 0x00000010
#define GPIO_SET_BIT5 0x00000020
#define GPIO_SET_BIT6 0x00000040
#define GPIO_SET_BIT7 0x00000080
#define GPIO_SET_BIT8 0x00000100
#define GPIO_SET_BIT9 0x00000200
#define GPIO_SET_BIT10 0x00000400
#define GPIO_SET_BIT11 0x00000800
#define GPIO_SET_BIT12 0x00001000
#define GPIO_SET_BIT13 0x00002000
#define GPIO_SET_BIT14 0x00004000
#define GPIO_SET_BIT15 0x00008000
#define GPIO_SET_BIT16 0x00010000
#define GPIO_SET_BIT17 0x00020000
#define GPIO_SET_BIT18 0x00040000
#define GPIO_SET_BIT19 0x00080000
#define GPIO_SET_BIT20 0x00100000
#define GPIO_SET_BIT21 0x00200000
#define GPIO_SET_BIT22 0x00400000
#define GPIO_SET_BIT23 0x00800000
#define GPIO_SET_BIT24 0x01000000
#define GPIO_SET_BIT25 0x02000000
#define GPIO_SET_BIT26 0x04000000
#define GPIO_SET_BIT27 0x08000000
#define GPIO_SET_BIT28 0x10000000
#define GPIO_SET_BIT29 0x20000000
#define GPIO_SET_BIT30 0x40000000
#define GPIO_SET_BIT31 0x80000000
/******************************************************************************
* hobbit1_2 gpio control and gpio reuse function
* selecting regester adddress
******************************************************************************/
#define HOBBIT1_2_GIPO0_PORTCTL_REG 0x50006008
#define HOBBIT1_2_GIPO1_PORTCTL_REG 0x50009008
#define HOBBIT1_2_IOMUX0L_REG 0x50006100
#define HOBBIT1_2_IOMUX0H_REG 0x50006104
#define HOBBIT1_2_IOMUX1L_REG 0x50006108
/*************basic gpio reuse v1.0********************************************
* UART1(PA16,PA17) for bootrom
* UART1(PA20,PA21) for console
******************************************************************************/
#define GPIO0_REUSE_EN (0x00000000)
#define GPIO0_REUSE_DIS (GPIO_SET_BIT16 | GPIO_SET_BIT17)
#define GPIO1_REUSE_EN (0x00000000)
#define IOMUX0L_FUNCTION_SEL (0x00000000)
#define IOMUX0H_FUNCTION_SEL (0x00000000)
#define IOMUX1L_FUNCTION_SEL (0x00000000)
#endif /* HOBBIT_PINMUX_H */

View file

@ -0,0 +1,328 @@
/*
* Copyright (C) 2017 C-SKY Microsystems Co., Ltd. All rights reserved.
*
* 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 soc.h
* @brief CSI Core Peripheral Access Layer Header File for
* CSKYSOC Device Series
* @version V1.0
* @date 02. June 2017
******************************************************************************/
#ifndef SOC_H
#define SOC_H
#ifdef __cplusplus
extern "C" {
#endif
#ifndef SYSTEM_CLOCK
#define SYSTEM_CLOCK (24000000)
#endif
#ifndef LSP_DEFAULT_FREQ
#define LSP_DEFAULT_FREQ (24000000)
#endif
/* ------------------------- Interrupt Number Definition ------------------------ */
typedef enum IRQn
{
/* ---------------------- CSKYCK801 Specific Interrupt Numbers --------------------- */
GPIOA_IRQn = 0, /* gpio Interrupt */
CORET_IRQn = 1, /* core Timer Interrupt */
TIMA0_IRQn = 2, /* timerA0 Interrupt */
TIMA1_IRQn = 3, /* timerA1 Interrupt */
I2S_IRQn = 4, /* i2s Interrupt */
WDT_IRQn = 5, /* wdt Interrupt */
UART0_IRQn = 6, /* uart0 Interrupt */
UART1_IRQn = 7, /* uart1 Interrupt */
UART2_IRQn = 8, /* uart2 Interrupt */
I2C0_IRQn = 9, /* i2c0 Interrupt */
I2C1_IRQn = 10, /* i2c1 Interrupt */
SPI1_IRQn = 11, /* spi0 Interrupt */
SPI0_IRQn = 12, /* spi1 Interrupt */
RTC_IRQn = 13, /* rtc Interrupt */
EXTWAK_IRQn = 14, /* extwakeup Interrupt */
ADC_IRQn = 15, /* adc interrupt */
CMP_IRQn = 16, /* cmp interrupt */
SEU_DMAC_IRQn = 17, /* seu dmac Interrupt */
POWM_IRQn = 18, /* powm Interrupt */
PWM_IRQn = 19, /* pwm Interrupt */
SYS_RESET_IRQn = 20, /* system reset Interrupt */
REV_IRQn = 21, /* rev Interrupt */
NONSEU_DMAC_IRQn = 22, /* nonuseu dmac Interrupt */
TIMB0_IRQn = 23, /* timerB0 Interrupt */
TIMB1_IRQn = 24, /* timerB1 Interrupt */
RTC1_IRQn = 25, /* rtc1 Interrupt */
AES_IRQn = 26, /* aes Interrupt */
GPIOB_IRQn = 27, /* trng Interrupt */
RSA_IRQn = 28, /* rsa Interrupt */
SHA_IRQn = 29, /* sha Interrupt */
}
IRQn_Type;
/* ================================================================================ */
/* ================ Processor and Core Peripheral Section ================ */
/* ================================================================================ */
/* -------- Configuration of the CK801 Processor and Core Peripherals ------- */
#define __CK802_REV 0x0000U /* Core revision r0p0 */
#define __MPU_PRESENT 0 /* MGU present or not */
#define __VIC_PRIO_BITS 2 /* Number of Bits used for Priority Levels */
#define __Vendor_SysTickConfig 0 /* Set to 1 if different SysTick Config is used */
#include "csi_core.h" /* Processor and core peripherals */
#include "stdint.h"
typedef enum {
CKENUM_DMA_UART0_RX,
CKENUM_DMA_UART0_TX,
CKENUM_DMA_UART1_RX,
CKENUM_DMA_UART1_TX,
CKENUM_DMA_ADC_RX,
CKENUM_DMA_ADC_TX,
CKENUM_DMA_SPI1_RX,
CKENUM_DMA_SPI1_TX,
CKENUM_DMA_SPI0_RX,
CKENUM_DMA_SPI0_TX,
CKENUM_DMA_IIC_RX,
CKENUM_DMA_IIC_TX,
CKENUM_DMA_IIC1_RX,
CKENUM_DMA_IIC1_TX,
CKENUM_DMA_IIS_RX,
CKENUM_DMA_IIS_TX,
CKENUM_DMA_MEMORY
} ckenum_dma_device_e;
/* ================================================================================ */
/* ================ Device Specific Peripheral Section ================ */
/* ================================================================================ */
#if 0
/* ================================================================================ */
/* ============== Universal Asyncronous Receiver / Transmitter (UART) ============= */
/* ================================================================================ */
typedef struct {
union {
__IM uint32_t RBR; /* Offset: 0x000 (R/ ) Receive buffer register */
__OM uint32_t THR; /* Offset: 0x000 ( /W) Transmission hold register */
__IOM uint32_t DLL; /* Offset: 0x000 (R/W) Clock frequency division low section register */
};
union {
__IOM uint32_t DLH; /* Offset: 0x004 (R/W) Clock frequency division high section register */
__IOM uint32_t IER; /* Offset: 0x004 (R/W) Interrupt enable register */
};
__IM uint32_t IIR; /* Offset: 0x008 (R/ ) Interrupt indicia register */
__IOM uint32_t LCR; /* Offset: 0x00C (R/W) Transmission control register */
__IOM uint32_t MCR; /* Offset: 0x010 (R/W) Modem control register */
__IM uint32_t LSR; /* Offset: 0x014 (R/ ) Transmission state register */
__IM uint32_t MSR; /* Offset: 0x018 (R/ ) Modem state register */
uint32_t RESERVED1[24];
__IM uint32_t USR; /* Offset: 0x07c (R/ ) UART state register */
} CSKY_UART_TypeDef;
/* ================================================================================ */
/* ============== Inter-Integrated Circuit (IIC) ============= */
/* ================================================================================ */
typedef struct {
__IOM uint32_t IC_CON; /* Offset: 0x000 (R/W) Receive buffer register */
__IOM uint32_t IC_TAR; /* Offset: 0x004 (R/W) Transmission hold register */
__IOM uint32_t IC_SAR; /* Offset: 0x008 (R/W) Clock frequency division low section register */
__IOM uint32_t IC_HS_MADDR; /* Offset: 0x00c (R/W) Clock frequency division high section register */
__IOM uint32_t IC_DATA_CMD; /* Offset: 0x010 (R/W) Interrupt enable register */
__IOM uint32_t IC_SS_SCL_HCNT; /* Offset: 0x014 (R/W) Interrupt indicia register */
__IOM uint32_t IC_SS_SCL_LCNT; /* Offset: 0x018 (R/W) Transmission control register */
__IOM uint32_t IC_FS_SCL_HCNT; /* Offset: 0x01c (R/W) Modem control register */
__IOM uint32_t IC_FS_SCL_LCNT; /* Offset: 0x020 (R/W) Transmission state register */
__IOM uint32_t IC_HS_SCL_HCNT; /* Offset: 0x024 (R/W) Transmission state register */
__IOM uint32_t IC_HS_SCL_LCNT; /* Offset: 0x028 (R/W) Transmission state register */
__IOM uint32_t IC_INTR_STAT; /* Offset: 0x02c (R) Transmission state register */
__IOM uint32_t IC_INTR_MASK; /* Offset: 0x030 (R/W) Transmission state register */
__IOM uint32_t IC_RAW_INTR_STAT; /* Offset: 0x034 (R) Transmission state register */
__IOM uint32_t IC_RX_TL; /* Offset: 0x038 (R/W) Transmission state register */
__IOM uint32_t IC_TX_TL; /* Offset: 0x03c (R/W) Transmission state register */
__IOM uint32_t IC_CLR_INTR; /* Offset: 0x040 (R) Transmission state register */
__IOM uint32_t IC_CLR_RX_UNDER; /* Offset: 0x044 (R) Transmission state register */
__IOM uint32_t IC_CLR_RX_OVER; /* Offset: 0x048 (R) Transmission state register */
__IOM uint32_t IC_CLR_TX_OVER; /* Offset: 0x04c (R) Transmission state register */
__IOM uint32_t IC_CLR_RD_REQ; /* Offset: 0x050 (R) Transmission state register */
__IOM uint32_t IC_CLR_TX_ABRT; /* Offset: 0x054 (R) Transmission state register */
__IOM uint32_t IC_CLR_RX_DONE; /* Offset: 0x058 (R) Transmission state register */
__IOM uint32_t IC_CLR_ACTIVITY; /* Offset: 0x05c (R) Transmission state register */
__IOM uint32_t IC_CLR_STOP_DET; /* Offset: 0x060 (R) Transmission state register */
__IOM uint32_t IC_CLR_START_DET; /* Offset: 0x064 (R) Transmission state register */
__IOM uint32_t IC_CLR_GEN_CALL; /* Offset: 0x068 (R) Transmission state register */
__IOM uint32_t IC_ENABLE; /* Offset: 0x06c (R/W) Transmission state register */
__IOM uint32_t IC_STATUS; /* Offset: 0x070 (R) Transmission state register */
__IOM uint32_t IC_TXFLR; /* Offset: 0x074 (R) Transmission state register */
__IOM uint32_t IC_RXFLR; /* Offset: 0x078 (R) Transmission state register */
uint32_t RESERVED; /* Offset: 0x014 (R/ ) Transmission state register */
__IOM uint32_t IC_TX_ABRT_SOURCE; /* Offset: 0x080 (R/W) Transmission state register */
__IOM uint32_t IC_SAR1; /* Offset: 0x084 (R/W) Transmission state register */
__IOM uint32_t IC_DMA_CR; /* Offset: 0x088 (R/W) Transmission state register */
__IOM uint32_t IC_DMA_TDLR; /* Offset: 0x08c (R/W) Transmission state register */
__IOM uint32_t IC_DMA_RDLR; /* Offset: 0x090 (R/W) Transmission state register */
__IOM uint32_t IC_SAR2; /* Offset: 0x094 (R/W) Transmission state register */
__IOM uint32_t IC_SAR3; /* Offset: 0x098 (R/W) Transmission state register */
__IOM uint32_t IC_MULTI_SLAVE; /* Offset: 0x09c (R/W) Transmission state register */
__IOM uint32_t IC_GEN_CALL_EN; /* Offset: 0x0a0 (R/W) Transmission state register */
} CSKY_IIC_TypeDef;
/* ================================================================================ */
/* ============== TIMER ============= */
/* ================================================================================ */
typedef struct {
__IOM uint32_t TxLoadCount; /* Offset: 0x000 (R/W) Receive buffer register */
__IOM uint32_t TxCurrentValue; /* Offset: 0x004 (R) Transmission hold register */
__IOM uint32_t TxControl; /* Offset: 0x008 (R/W) Clock frequency division low section register */
__IOM uint32_t TxEOI; /* Offset: 0x00c (R) Clock frequency division high section register */
__IOM uint32_t TxIntStatus; /* Offset: 0x010 (R) Interrupt enable register */
} CSKY_TIMER_TypeDef;
/* ================================================================================ */
/* ============== TIMER Control ============= */
/* ================================================================================ */
typedef struct {
__IOM uint32_t TimersIntStatus; /* Offset: 0x000 (R) Interrupt indicia register */
__IOM uint32_t TimerEOI; /* Offset: 0x004 (R) Transmission control register */
__IOM uint32_t TimerRawIntStatus; /* Offset: 0x008 (R) Modem control register */
} CSKY_TIMER_Control_TypeDef;
/* ================================================================================ */
/* ============== GPIO ============= */
/* ================================================================================ */
typedef struct {
__IOM uint32_t SWPORT_DR; /* Offset: 0x000 (R/W) Interrupt indicia register */
__IOM uint32_t SWPORT_DDR; /* Offset: 0x004 (R/W) Interrupt indicia register */
__IOM uint32_t PORT_CTL; /* Offset: 0x008 (R/W) Interrupt indicia register */
} CKStruct_GPIO, *PCKStruct_GPIO;
typedef struct {
__IOM uint32_t SHA_CON; /* Offset: 0x000 (R/W) Control register */
__IOM uint32_t SHA_INTSTATE; /* Offset: 0x004 (R/W) Instatus register */
__IOM uint32_t SHA_H0L; /* Offset: 0x008 (R/W) H0L register */
__IOM uint32_t SHA_H1L; /* Offset: 0x00c (R/W) H1L register */
__IOM uint32_t SHA_H2L; /* Offset: 0x010 (R/W) H2L register */
__IOM uint32_t SHA_H3L; /* Offset: 0x014 (R/W) H3L register */
__IOM uint32_t SHA_H4L; /* Offset: 0x018 (R/W) H4L register */
__IOM uint32_t SHA_H5L; /* Offset: 0x01c (R/W) H5L register */
__IOM uint32_t SHA_H6L; /* Offset: 0x020 (R/W) H6L register */
__IOM uint32_t SHA_H7L; /* Offset: 0x024 (R/W) H7L register */
__IOM uint32_t SHA_H0H; /* Offset: 0x028 (R/W) H0H register */
__IOM uint32_t SHA_H1H; /* Offset: 0x02c (R/W) H1H register */
__IOM uint32_t SHA_H2H; /* Offset: 0x030 (R/W) H2H register */
__IOM uint32_t SHA_H3H; /* Offset: 0x034 (R/W) H3H register */
__IOM uint32_t SHA_H4H; /* Offset: 0x038 (R/W) H4H register */
__IOM uint32_t SHA_H5H; /* Offset: 0x03c (R/W) H5H register */
__IOM uint32_t SHA_H6H; /* Offset: 0x040 (R/W) H6H register */
__IOM uint32_t SHA_H7H; /* Offset: 0x044 (R/W) H7H register */
__IOM uint32_t SHA_DATA1; /* Offset: 0x048 (R/W) DATA1 register */
uint32_t REV[15];
__IOM uint32_t SHA_DATA2; /* Offset: 0x088 (R/W) DATA2 register */
} CSKY_SHA_TypeDef;
#endif
#define CONFIG_CRC_NUM 1
#define CONFIG_EFLASH_NUM 1
#define CONFIG_IIC_NUM 2
#define CONFIG_TRNG_NUM 1
#define CONFIG_AES_NUM 1
#define CONFIG_RSA_NUM 1
#define CONFIG_SHA_NUM 1
#define CONFIG_SPI_NUM 2
#define CONFIG_PWM_NUM 6
#define CONFIG_TIMER_NUM 4
#define CONFIG_RTC_NUM 2
#define CONFIG_WDT_NUM 1
#define CONFIG_DMAC_NUM 2
#define CONFIG_GPIO_NUM 2
#define CONFIG_GPIO_PIN_NUM 32
#define CONFIG_USART_NUM 3
#define CONFIG_ETH_NUM 2
#define CONFIG_ADC_NUM 1
/* ================================================================================ */
/* ================ Peripheral memory map ================ */
/* ================================================================================ */
/* -------------------------- CHIP memory map ------------------------------- */
#define CSKY_EFLASH_BASE (0x10000000UL)
#define CSKY_SRAM_BASE (0x60000000UL)
/* AHB */
#define CSKY_AHB_ARB_BASE (0x40000000UL)
#define CSKY_DMAC0_BASE (0x40001000UL)
#define CSKY_CLKGEN_BASE (0x40002000UL)
#define CSKY_CRC_BASE (0x40003000UL)
#define CSKY_DMAC1_BASE (0x40004000UL)
#define CSKY_OTP_BASE (0x4003F000UL)
#define CSKY_AES_BASE (0x40006000UL)
#define CSKY_SRAM_SASC_BASE (0x40007000UL)
#define CSKY_SHA_BASE (0x40008000UL)
#define CSKY_TRNG_BASE (0x40009000UL)
#define CSKY_RSA_BASE (0x4000a000UL)
#define CSKY_EFLASH_CONTROL_BASE (0x4003f000UL)
#define CSKY_APB0_BRIDGE_BASE (0x50000000UL)
#define CSKY_APB1_BRIDGE_BASE (0x50010000UL)
/* APB0 */
#define CSKY_WDT_BASE (0x50001000UL)
#define CSKY_SPI0_BASE (0x50002000UL)
#define CSKY_RTC0_BASE (0x50003000UL)
#define CSKY_UART0_BASE (0x50004000UL)
#define CSKY_UART1_BASE (0x50005000UL)
#define CSKY_GPIO0_BASE (0x50006000UL)
#define CSKY_I2C0_BASE (0x50007000UL)
#define CSKY_I2S_BASE (0x50008000UL)
#define CSKY_GPIO1_BASE (0x50009000UL)
#define CSKY_SIPC_BASE (0x5000a000UL)
/* APB1 */
#define CSKY_TIM0_BASE (0x50011000UL)
#define CSKY_SPI1_BASE (0x50012000UL)
#define CSKY_I2C1_BASE (0x50013000UL)
#define CSKY_PWM_BASE (0x50014000UL)
#define CSKY_UART2_BASE (0x50015000UL)
#define CSKY_ADC_CTL_BASE (0x50016000UL)
#define CSKY_CMP_CTL_BASE (0x50017000UL)
#define CSKY_ETB_BASE (0x50018000UL)
#define CSKY_TIM1_BASE (0x50019000UL)
#define CSKY_RTC1_BASE (0x5001a000UL)
#define SHA_CONTEXT_SIZE 224
/* ================================================================================ */
/* ================ Peripheral declaration ================ */
/* ================================================================================ */
#define CSKY_UART1 (( CSKY_UART_TypeDef *) CSKY_UART1_BASE)
#define CSKY_SHA (( CSKY_SHA_TypeDef *) CSKY_SHA_BASE)
#ifdef __cplusplus
}
#endif
#endif /* SOC_H */

View file

@ -0,0 +1,247 @@
/*
* Copyright (C) 2017 C-SKY Microsystems Co., Ltd. All rights reserved.
*
* 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 isr.c
* @brief source file for the interrupt server route
* @version V1.0
* @date 25. August 2017
******************************************************************************/
#include <drv_common.h>
#include <csi_config.h>
#include "soc.h"
#ifndef CONFIG_KERNEL_NONE
#include <csi_kernel.h>
#endif
extern void dw_usart_irqhandler(int32_t idx);
extern void dw_timer_irqhandler(int32_t idx);
extern void dw_gpio_irqhandler(int32_t idx);
extern void dw_iic_irqhandler(int32_t idx);
extern void ck_rtc_irqhandler(int32_t idx);
extern void dw_spi_irqhandler(int32_t idx);
extern void dw_wdt_irqhandler(int32_t idx);
extern void ck_dma_irqhandler(int32_t idx);
extern void ck_aes_irqhandler(int32_t idx);
extern void ck_sha_irqhandler(int32_t idx);
extern void dw_dmac_irqhandler(int32_t idx);
extern void ck_adc_irqhandler(int32_t idx);
#ifdef CONFIG_KERNEL_FREERTOS
extern void CoretimeIsr(void);
extern void CKPendSVIsr(void);
#endif
extern void systick_handler(void);
extern void xPortSysTickHandler(void);
extern void OSTimeTick(void);
#define readl(addr) \
({ unsigned int __v = (*(volatile unsigned int *) (addr)); __v; })
#ifndef CONFIG_KERNEL_NONE
#define CSI_INTRPT_ENTER() csi_kernel_intrpt_enter()
#define CSI_INTRPT_EXIT() csi_kernel_intrpt_exit()
#else
#define CSI_INTRPT_ENTER()
#define CSI_INTRPT_EXIT()
#endif
#ifdef CONFIG_HAVE_VIC
#define ATTRIBUTE_ISR __attribute__((isr))
#else
#define ATTRIBUTE_ISR
#endif
ATTRIBUTE_ISR void CORET_IRQHandler(void)
{
#ifndef CONFIG_KERNEL_FREERTOS
CSI_INTRPT_ENTER();
#endif
readl(0xE000E010);
#if defined(CONFIG_KERNEL_RHINO)
systick_handler();
#elif defined(CONFIG_KERNEL_FREERTOS)
xPortSysTickHandler();
#elif defined(CONFIG_KERNEL_UCOS)
OSTimeTick();
#endif
#ifndef CONFIG_KERNEL_FREERTOS
CSI_INTRPT_EXIT();
#endif
}
ATTRIBUTE_ISR void USART0_IRQHandler(void)
{
CSI_INTRPT_ENTER();
dw_usart_irqhandler(0);
CSI_INTRPT_EXIT();
}
ATTRIBUTE_ISR void USART1_IRQHandler(void)
{
CSI_INTRPT_ENTER();
dw_usart_irqhandler(1);
CSI_INTRPT_EXIT();
}
ATTRIBUTE_ISR void USART2_IRQHandler(void)
{
CSI_INTRPT_ENTER();
dw_usart_irqhandler(2);
CSI_INTRPT_EXIT();
}
ATTRIBUTE_ISR void USART3_IRQHandler(void)
{
CSI_INTRPT_ENTER();
dw_usart_irqhandler(3);
CSI_INTRPT_EXIT();
}
ATTRIBUTE_ISR void TIMA0_IRQHandler(void)
{
CSI_INTRPT_ENTER();
dw_timer_irqhandler(0);
CSI_INTRPT_EXIT();
}
ATTRIBUTE_ISR void TIMA1_IRQHandler(void)
{
CSI_INTRPT_ENTER();
dw_timer_irqhandler(1);
CSI_INTRPT_EXIT();
}
ATTRIBUTE_ISR void TIMB0_IRQHandler(void)
{
CSI_INTRPT_ENTER();
dw_timer_irqhandler(2);
CSI_INTRPT_EXIT();
}
ATTRIBUTE_ISR void TIMB1_IRQHandler(void)
{
CSI_INTRPT_ENTER();
dw_timer_irqhandler(3);
CSI_INTRPT_EXIT();
}
ATTRIBUTE_ISR void GPIO0_IRQHandler(void)
{
CSI_INTRPT_ENTER();
dw_gpio_irqhandler(0);
CSI_INTRPT_EXIT();
}
ATTRIBUTE_ISR void GPIO1_IRQHandler(void)
{
CSI_INTRPT_ENTER();
dw_gpio_irqhandler(1);
CSI_INTRPT_EXIT();
}
ATTRIBUTE_ISR void I2C0_IRQHandler(void)
{
CSI_INTRPT_ENTER();
dw_iic_irqhandler(0);
CSI_INTRPT_EXIT();
}
ATTRIBUTE_ISR void I2C1_IRQHandler(void)
{
CSI_INTRPT_ENTER();
dw_iic_irqhandler(1);
CSI_INTRPT_EXIT();
}
ATTRIBUTE_ISR void RTC_IRQHandler(void)
{
CSI_INTRPT_ENTER();
ck_rtc_irqhandler(0);
CSI_INTRPT_EXIT();
}
ATTRIBUTE_ISR void RTC1_IRQHandler(void)
{
CSI_INTRPT_ENTER();
ck_rtc_irqhandler(1);
CSI_INTRPT_EXIT();
}
ATTRIBUTE_ISR void AES_IRQHandler(void)
{
CSI_INTRPT_ENTER();
ck_aes_irqhandler(0);
CSI_INTRPT_EXIT();
}
ATTRIBUTE_ISR void TRNG_IRQHandler(void)
{
CSI_INTRPT_ENTER();
CSI_INTRPT_EXIT();
}
ATTRIBUTE_ISR void RSA_IRQHandler(void)
{
CSI_INTRPT_ENTER();
CSI_INTRPT_EXIT();
}
ATTRIBUTE_ISR void SPI0_IRQHandler(void)
{
CSI_INTRPT_ENTER();
dw_spi_irqhandler(0);
CSI_INTRPT_EXIT();
}
ATTRIBUTE_ISR void SPI1_IRQHandler(void)
{
CSI_INTRPT_ENTER();
dw_spi_irqhandler(1);
CSI_INTRPT_EXIT();
}
ATTRIBUTE_ISR void WDT_IRQHandler(void)
{
CSI_INTRPT_ENTER();
dw_wdt_irqhandler(0);
CSI_INTRPT_EXIT();
}
ATTRIBUTE_ISR void DMAC0_IRQHandler(void)
{
CSI_INTRPT_ENTER();
dw_dmac_irqhandler(0);
CSI_INTRPT_EXIT();
}
ATTRIBUTE_ISR void DMAC1_IRQHandler(void)
{
CSI_INTRPT_ENTER();
dw_dmac_irqhandler(1);
CSI_INTRPT_EXIT();
}
ATTRIBUTE_ISR void ADC_IRQHandler(void)
{
CSI_INTRPT_ENTER();
ck_adc_irqhandler(0);
CSI_INTRPT_EXIT();
}

View file

@ -0,0 +1,156 @@
/*
* Copyright (C) 2017 C-SKY Microsystems Co., Ltd. All rights reserved.
*
* 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 lib.c
* @brief source file for the lib
* @version V1.0
* @date 02. June 2017
******************************************************************************/
#include <csi_config.h>
#include <stdint.h>
#include <stdarg.h>
#include <stdio.h>
#include "soc.h"
#include "csi_core.h" //for test
#include "drv_usart.h"
#include "drv_timer.h"
#ifndef CONFIG_LPM_TICKLESS_SLEEP
extern uint32_t csi_coret_get_load(void);
extern uint32_t csi_coret_get_value(void);
#else
timer_handle_t system_timer;
timer_handle_t count_timer;
#endif
extern int32_t csi_usart_putchar(usart_handle_t handle, uint8_t ch);
extern int32_t csi_usart_getchar(usart_handle_t handle, uint8_t *ch);
static void _mdelay(void)
{
#ifdef CONFIG_LPM_TICKLESS_SLEEP
uint32_t load;
uint32_t start;
uint32_t cur;
uint32_t cnt = (SYSTEM_CLOCK / 1000);
csi_timer_get_load_value(count_timer, &load);
csi_timer_get_current_value(count_timer, &start);
while (1) {
csi_timer_get_current_value(count_timer, &cur);
if (start > cur) {
if (start - cur >= cnt) {
return;
}
} else {
if (cur + load - start > cnt) {
return;
}
}
}
#else
uint32_t load = csi_coret_get_load();
uint32_t start = csi_coret_get_value();
uint32_t cur;
uint32_t cnt = (SYSTEM_CLOCK / 1000);
while (1) {
cur = csi_coret_get_value();
if (start > cur) {
if (start - cur >= cnt) {
return;
}
} else {
if (cur + load - start > cnt) {
return;
}
}
}
#endif
}
void mdelay(uint32_t ms)
{
if (ms == 0) {
return;
}
while (ms--) {
_mdelay();
}
}
static void _10udelay(void)
{
#ifdef CONFIG_LPM_TICKLESS_SLEEP
uint32_t load;
uint32_t start;
uint32_t cur;
uint32_t cnt = (SYSTEM_CLOCK / 1000 / 100);
csi_timer_get_load_value(count_timer, &load);
csi_timer_get_current_value(count_timer, &start);
while (1) {
csi_timer_get_current_value(count_timer, &cur);
if (start > cur) {
if (start - cur >= cnt) {
return;
}
} else {
if (cur + load - start > cnt) {
return;
}
}
}
#else
uint32_t load = csi_coret_get_load();
uint32_t start = csi_coret_get_value();
uint32_t cur;
uint32_t cnt = (SYSTEM_CLOCK / 1000 / 100);
while (1) {
cur = csi_coret_get_value();
if (start > cur) {
if (start - cur >= cnt) {
return;
}
} else {
if (cur + load - start > cnt) {
return;
}
}
}
#endif
}
void udelay(uint32_t us)
{
us = (us / 10) - 1;
if (us == 0) {
return;
}
while (us--) {
_10udelay();
}
}

View file

@ -0,0 +1,75 @@
/*
* Copyright (C) 2016 YunOS Project. All rights reserved.
*
* 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.
*/
#include <csi_config.h>
extern void NOVIC_IRQ_Default_Handler(void);
extern void CORET_IRQHandler(void);
extern void TIMA0_IRQHandler(void);
extern void TIMA1_IRQHandler(void);
extern void TIMB0_IRQHandler(void);
extern void TIMB1_IRQHandler(void);
extern void WDT_IRQHandler(void);
extern void USART0_IRQHandler(void);
extern void USART1_IRQHandler(void);
extern void USART2_IRQHandler(void);
extern void USART3_IRQHandler(void);
extern void I2C0_IRQHandler(void);
extern void I2C1_IRQHandler(void);
extern void SPI0_IRQHandler(void);
extern void SPI1_IRQHandler(void);
extern void GPIO0_IRQHandler(void);
extern void GPIO1_IRQHandler(void);
extern void RTC_IRQHandler(void);
extern void RTC1_IRQHandler(void);
extern void AES_IRQHandler(void);
extern void SHA_IRQHandler(void);
extern void RSA_IRQHandler(void);
extern void ADC_IRQHandler(void);
void (*g_irqvector[])(void) = {
GPIO0_IRQHandler, /* 0, default interrupt entry */
CORET_IRQHandler, /* 1, default interrupt entry */
TIMA0_IRQHandler, /* 2, default interrupt entry */
TIMA1_IRQHandler, /* 3, default interrupt entry */
NOVIC_IRQ_Default_Handler, /* 4, default interrupt entry */
WDT_IRQHandler, /* 5, default interrupt entry */
USART0_IRQHandler, /* 6, default interrupt entry */
USART1_IRQHandler, /* 7, default interrupt entry */
USART2_IRQHandler, /* 8, default interrupt entry */
I2C0_IRQHandler, /* 9, default interrupt entry */
I2C1_IRQHandler, /* 10, default interrupt entry */
SPI1_IRQHandler, /* 11, default interrupt entry */
SPI0_IRQHandler, /* 12, default interrupt entry */
RTC_IRQHandler, /* 13, default interrupt entry */
NOVIC_IRQ_Default_Handler, /* 14, default interrupt entry */
ADC_IRQHandler, /* 15, ADC */
NOVIC_IRQ_Default_Handler, /* 16, default interrupt entry */
NOVIC_IRQ_Default_Handler, /* 17, default interrupt entry */
NOVIC_IRQ_Default_Handler, /* 18, default interrupt entry */
NOVIC_IRQ_Default_Handler, /* 19, default interrupt entry */
NOVIC_IRQ_Default_Handler, /* 20, default interrupt entry */
NOVIC_IRQ_Default_Handler, /* 21, default interrupt entry */
NOVIC_IRQ_Default_Handler, /* 22, default interrupt entry */
TIMB0_IRQHandler, /* 23, default interrupt entry */
TIMB1_IRQHandler, /* 24, default interrupt entry */
NOVIC_IRQ_Default_Handler, /* 25, default interrupt entry */
AES_IRQHandler, /* 26, default interrupt entry */
GPIO1_IRQHandler, /* 27, default interrupt entry */
RSA_IRQHandler, /* 28, default interrupt entry */
SHA_IRQHandler, /* 29, default interrupt entry */
};

View file

@ -0,0 +1,161 @@
/*
* Copyright (C) 2017 C-SKY Microsystems Co., Ltd. All rights reserved.
*
* 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 pinmux.c
* @brief source file for the pinmux
* @version V1.0
* @date 02. June 2017
******************************************************************************/
#include <csi_config.h>
#include <stdint.h>
#include "pinmux.h"
#include "pin_name.h"
#include <drv_gpio.h>
#define readl(addr) \
({ unsigned int __v = (*(volatile unsigned int *) (addr)); __v; })
#define writel(b,addr) (void)((*(volatile unsigned int *) (addr)) = (b))
/*******************************************************************************
* function: hobbit_ioreuse_inital
*
* description:
* initial hobbit_pinmux
*******************************************************************************/
void hobbit_ioreuse_initial(void)
{
unsigned int value;
value = readl(HOBBIT1_2_GIPO0_PORTCTL_REG);
value &= ~(GPIO0_REUSE_DIS);
writel(value, HOBBIT1_2_GIPO0_PORTCTL_REG);
}
int32_t pin_mux(pin_name_t pin, uint16_t function)
{
unsigned int val = 0;
unsigned int reg_val = 0;
uint8_t offset;
if (function > 3) {
if (pin <= PB3_SPI0MISO_PWM5_I2SSD) {
if (pin <= PA5_RTS0_PWM1_SPI0SSN_TRIG1) {
offset = pin;
/* gpio data source select */
val = readl(HOBBIT1_2_GIPO0_PORTCTL_REG);
val &= ~(1 << offset);
writel(val, HOBBIT1_2_GIPO0_PORTCTL_REG);
return 0;
} else if (pin >= PB0_SCL0_PWM2_I2SMCLK) {
offset = pin - 6;
/* gpio data source select */
val = readl(HOBBIT1_2_GIPO1_PORTCTL_REG);
val &= ~(1 << offset);
writel(val, HOBBIT1_2_GIPO1_PORTCTL_REG);
return 0;
}
}
if ((pin >= PA6_SPI0MOSI_PWM6_SCL0) && (pin <= PA27_RTS2_I2SSD_ADC13)) {
offset = pin - 4;
/* gpio data source select */
val = readl(HOBBIT1_2_GIPO0_PORTCTL_REG);
val &= ~(1 << offset);
writel(val, HOBBIT1_2_GIPO0_PORTCTL_REG);
return 0;
}
return -1;
}
if ((pin >= PA6_SPI0MOSI_PWM6_SCL0) && (pin <= PA27_RTS2_I2SSD_ADC13)) {
offset = pin - 4;
/* gpio data source select */
val = readl(HOBBIT1_2_GIPO0_PORTCTL_REG);
val |= (1 << offset);
writel(val, HOBBIT1_2_GIPO0_PORTCTL_REG);
if (pin <= PA11_ACMP0N_ADC3_RXD0) {
offset = pin;
reg_val = (0x3 << (offset * 2));
/* reuse function select */
val = readl(HOBBIT1_2_IOMUX0L_REG);
val &= ~(reg_val);
val |= (function << (2 * offset));
writel(val, HOBBIT1_2_IOMUX0L_REG);
return 0;
} else {
offset = pin - 16;
reg_val = (0x3 << (offset * 2));
/* reuse function select */
val = readl(HOBBIT1_2_IOMUX0H_REG);
val &= ~(reg_val);
val |= (function << (2 * offset));
writel(val, HOBBIT1_2_IOMUX0H_REG);
return 0;
}
}
if ((pin >= PA0_TRIG0_ACMP1P_TCK) && (pin <= PB3_SPI0MISO_PWM5_I2SSD)) {
if (pin >= PB0_SCL0_PWM2_I2SMCLK) {
offset = pin - 6;
val = readl(HOBBIT1_2_GIPO1_PORTCTL_REG);
val |= (1 << offset);
writel(val, HOBBIT1_2_GIPO1_PORTCTL_REG);
offset = pin;
reg_val = (0x3 << (offset * 2));
/* reuse function select */
val = readl(HOBBIT1_2_IOMUX0L_REG);
val &= ~(reg_val);
val |= (function << (2 * offset));
writel(val, HOBBIT1_2_IOMUX0L_REG);
return 0;
}
if (pin <= PA5_RTS0_PWM1_SPI0SSN_TRIG1) {
offset = pin;
/* gpio data source select */
val = readl(HOBBIT1_2_GIPO0_PORTCTL_REG);
val |= (1 << offset);
writel(val, HOBBIT1_2_GIPO0_PORTCTL_REG);
reg_val = (0x3 << (offset * 2));
/* reuse function select */
val = readl(HOBBIT1_2_IOMUX0L_REG);
val &= ~(reg_val);
val |= (function << (2 * offset));
writel(val, HOBBIT1_2_IOMUX0L_REG);
return 0;
}
}
if (pin > PA27_RTS2_I2SSD_ADC13) {
offset = pin - PC0_SCL1_CTS1_PWM10_ADC14;
reg_val = (0x3 << (offset *2));
val = readl(HOBBIT1_2_IOMUX1L_REG);
val &= ~(reg_val);
val |= (function << (2 * offset));
writel(val, HOBBIT1_2_IOMUX1L_REG);
}
return -1;
}

View file

@ -0,0 +1,305 @@
/*
* Copyright (C) 2017 C-SKY Microsystems Co., Ltd. All rights reserved.
*
* 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 startup.S
* @brief startup file for HOBBIT1_2. Should use with
* GCC for CSKY Embedded Processors
* @version V1.0
* @date 24. August 2017
******************************************************************************/
#include <csi_config.h>
#undef EFLASH_CONTROL_BASE
#define EFLASH_CONTROL_BASE 0x4003f000
#undef PMU_LP_CONTROL
#define PMU_LP_CONTROL 0x40002000
#undef PMU_MCLK_SEL
#define PMU_MCLK_SEL 0x40002004
#undef PMU_CLK_STABLE
#define PMU_CLK_STABLE 0x40002018
#undef PMU_PLL_CTRL
#define PMU_PLL_CTRL 0x4000202c
.import CKTrap0ISR
.import NOVIC_IRQ_Default_Handler
.import NOVIC_CORETIM_Handler
.import Default_Handler
.section .vectors
.align 10
.globl __Vectors
.type __Vectors, @object
__Vectors:
.long Reset_Handler /* Reset Handler */
.long Default_Handler
.long Default_Handler
.long Default_Handler
.long Default_Handler
.long Default_Handler
.long Default_Handler
.long Default_Handler
.long Default_Handler
.long Default_Handler
.long Default_Handler
.long Default_Handler
.long Default_Handler
.long Default_Handler
.long Default_Handler
.long Default_Handler
#ifdef CONFIG_KERNEL_FREERTOS
.long CKTrap0ISR
#else
.long Default_Handler
#endif
.long Default_Handler
.long Default_Handler
.long Default_Handler
.long Default_Handler
.long Default_Handler
.long Default_Handler
.long Default_Handler
.long Default_Handler
.long Default_Handler
.long Default_Handler
.long Default_Handler
.long Default_Handler
.long Default_Handler
.long Default_Handler
.long Default_Handler
#ifdef CONFIG_KERNEL_NONE
/* External interrupts */
.long GPIO0_IRQHandler /* 0: GPIO */
.long CORET_IRQHandler /* 1: core Timer */
.long TIMA0_IRQHandler /* 2: TimerA0 */
.long TIMA1_IRQHandler /* 3: TimerA1 */
.long Default_Handler
.long WDT_IRQHandler /* 5: WDT */
.long USART0_IRQHandler /* 6: UART0 */
.long USART1_IRQHandler /* 7: UART1 */
.long USART2_IRQHandler /* 8: UART2 */
.long I2C0_IRQHandler /* 9: I2C0 */
.long I2C1_IRQHandler /* 10: I2C1 */
.long SPI1_IRQHandler /* 11: SPI1 */
.long SPI0_IRQHandler /* 12: SPI0 */
.long RTC_IRQHandler /* 13: RTC */
.long Default_Handler
.long ADC_IRQHandler /* 15: ADC */
.long Default_Handler
.long DMAC0_IRQHandler /* 17: DMAC0 */
.long Default_Handler
.long Default_Handler
.long Default_Handler
.long Default_Handler
.long DMAC1_IRQHandler /* 22: DMAC1 */
.long TIMB0_IRQHandler /* 23: TimerB0 */
.long TIMB1_IRQHandler /* 24: TimerB1 */
.long RTC1_IRQHandler /* 25: RTC1 */
.long AES_IRQHandler /* 26: AES */
.long GPIO1_IRQHandler
.long RSA_IRQHandler /* 28: RSA */
.long SHA_IRQHandler /* 29: SHA */
#else
.long NOVIC_IRQ_Default_Handler /* default interrupt entry */
#ifdef CONFIG_KERNEL_FREERTOS
.long NOVIC_CORETIM_Handler /* novic coretime handler specific*/
#else
.long NOVIC_IRQ_Default_Handler /* default interrupt entry */
#endif
.long NOVIC_IRQ_Default_Handler /* default interrupt entry */
.long NOVIC_IRQ_Default_Handler /* default interrupt entry */
.long NOVIC_IRQ_Default_Handler /* default interrupt entry */
.long NOVIC_IRQ_Default_Handler /* default interrupt entry */
.long NOVIC_IRQ_Default_Handler /* default interrupt entry */
.long NOVIC_IRQ_Default_Handler /* default interrupt entry */
.long NOVIC_IRQ_Default_Handler /* default interrupt entry */
.long NOVIC_IRQ_Default_Handler /* default interrupt entry */
.long NOVIC_IRQ_Default_Handler /* default interrupt entry */
.long NOVIC_IRQ_Default_Handler /* default interrupt entry */
.long NOVIC_IRQ_Default_Handler /* default interrupt entry */
.long NOVIC_IRQ_Default_Handler /* default interrupt entry */
.long NOVIC_IRQ_Default_Handler /* default interrupt entry */
.long NOVIC_IRQ_Default_Handler /* default interrupt entry */
.long NOVIC_IRQ_Default_Handler /* default interrupt entry */
.long NOVIC_IRQ_Default_Handler /* default interrupt entry */
.long NOVIC_IRQ_Default_Handler /* default interrupt entry */
.long NOVIC_IRQ_Default_Handler /* default interrupt entry */
.long NOVIC_IRQ_Default_Handler /* default interrupt entry */
.long NOVIC_IRQ_Default_Handler /* default interrupt entry */
.long NOVIC_IRQ_Default_Handler /* default interrupt entry */
.long NOVIC_IRQ_Default_Handler /* default interrupt entry */
.long NOVIC_IRQ_Default_Handler /* default interrupt entry */
.long NOVIC_IRQ_Default_Handler /* default interrupt entry */
.long NOVIC_IRQ_Default_Handler /* default interrupt entry */
.long NOVIC_IRQ_Default_Handler /* default interrupt entry */
.long NOVIC_IRQ_Default_Handler /* default interrupt entry */
.long NOVIC_IRQ_Default_Handler /* default interrupt entry */
.long NOVIC_IRQ_Default_Handler /* default interrupt entry */
.long NOVIC_IRQ_Default_Handler /* default interrupt entry */
#endif
.size __Vectors, . - __Vectors
.text
.long _start
.align 1
_start:
.text
.align 1
.globl Reset_Handler
.type Reset_Handler, %function
Reset_Handler:
lrw r0, PMU_LP_CONTROL
ldw r1, (r0, 0)
btsti r1, 5
bf .LSetClk
lrw r0, EFLASH_CONTROL_BASE
movi r1, 0x35
stw r1, (r0, 0x24)
movi r1, 0x16
stw r1, (r0, 0x28)
movi r1, 0x35
stw r1, (r0, 0x2c)
movi r1, 0x1b9
stw r1, (r0, 0x30)
movi r1, 0x8b10
stw r1, (r0, 0x34)
.LSetClk:
/* set clk 24MHz */
lrw r0, PMU_PLL_CTRL
lrw r1, 0xc0206
stw r1, (r0)
lrw r0, PMU_CLK_STABLE
lrw r2, 10000
.LWaitClkStabe:
subi r2, 1
cmpnei r2, 0
bf .Ltimeout
ldw r1, (r0)
btsti r1, 4
bf .LWaitClkStabe
.Ltimeout:
lrw r0, PMU_MCLK_SEL
movi r1, 0x8
stw r1, (r0)
/* Enable instruction cache */
lrw r0, 0xe000f000 /* Cache register base address */
lrw r1, 0x10000063 /* CRCR0 value means: Cached data from 0x100000000, Size=256KB, Enable*/
stw r1, (r0, 0x8) /* store 0x10000063 to CRCR0(0xe000f008) */
lrw r1, 0x1 /* store 0x1 to r1 */
stw r1, (r0, 0x4) /* set CIR(0xe000f004) to 0x1, means invalid all caches */
lrw r1, 0x3 /* store 0x3 to r1 */
stw r1, (r0, 0x0) /* set CER(0xe000f000) to 0x3, means enable icache */
/* under normal circumstances, it should not be opened */
#ifndef CONFIG_SYSTEM_SECURE
lrw r0, 0x80000000
mtcr r0, psr
#else
lrw r0, 0xe0000000
mtcr r0, psr
#endif
/* Initialize the normal stack pointer from the linker definition. */
lrw a1, __StackTop
mov sp, a1
/*
* The ranges of copy from/to are specified by following symbols
* __etext: LMA of start of the section to copy from. Usually end of text
* __data_start__: VMA of start of the section to copy to
* __data_end__: VMA of end of the section to copy to
*
* All addresses must be aligned to 4 bytes boundary.
*/
lrw r1, __erodata
lrw r2, __data_start__
lrw r3, __data_end__
subu r3, r2
cmpnei r3, 0
bf .L_loop0_done
.L_loop0:
ldw r0, (r1, 0)
stw r0, (r2, 0)
addi r1, 4
addi r2, 4
subi r3, 4
cmpnei r3, 0
bt .L_loop0
.L_loop0_done:
/*
* The BSS section is specified by following symbols
* __bss_start__: start of the BSS section.
* __bss_end__: end of the BSS section.
*
* Both addresses must be aligned to 4 bytes boundary.
*/
lrw r1, __bss_start__
lrw r2, __bss_end__
movi r0, 0
subu r2, r1
cmpnei r2, 0
bf .L_loop1_done
.L_loop1:
stw r0, (r1, 0)
addi r1, 4
subi r2, 4
cmpnei r2, 0
bt .L_loop1
.L_loop1_done:
#ifndef __NO_SYSTEM_INIT
bsr SystemInit
#endif
#ifndef __NO_BOARD_INIT
bsr board_init
#endif
bsr main
.size Reset_Handler, . - Reset_Handler
__exit:
br __exit
.section .bss
.align 2
.globl g_intstackalloc
.global g_intstackbase
.global g_top_irqstack
g_intstackalloc:
g_intstackbase:
.space CONFIG_ARCH_INTERRUPTSTACK
g_top_irqstack:
.end

View file

@ -0,0 +1,99 @@
/*
* Copyright (C) 2017 C-SKY Microsystems Co., Ltd. All rights reserved.
*
* 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 system.c
* @brief CSI Device System Source File
* @version V1.0
* @date 02. June 2017
******************************************************************************/
#include <csi_config.h>
#include "soc.h"
#include "csi_core.h"
#include "drv_timer.h"
#ifndef CONFIG_SYSTICK_HZ
#define CONFIG_SYSTICK_HZ 100
#endif
#ifndef CONFIG_LPM_TICKLESS_SYSTIM
#define CONFIG_LPM_TICKLESS_SYSTIM 0
#endif
#ifndef CONFIG_LPM_TICKLESS_CNTTIM
#define CONFIG_LPM_TICKLESS_CNTTIM 1
#endif
extern timer_handle_t system_timer;
extern timer_handle_t count_timer;
extern void systick_handler(void);
/*----------------------------------------------------------------------------
System Core Clock Variable
*----------------------------------------------------------------------------*/
int SystemCoreClock = SYSTEM_CLOCK; /* System Core Clock Frequency */
void SystemCoreClockUpdate(void)
{
SystemCoreClock = SYSTEM_CLOCK;
}
/**
* @brief initialize the system
* Initialize the psr and vbr.
* @param None
* @return None
*/
__attribute__((weak)) void SystemInit(void)
{
/* Here we may setting exception vector, MGU, cache, and so on. */
__set_VBR((uint32_t) & (__Vectors));
#ifdef CONFIG_KERNEL_NONE
#ifdef CONFIG_SYSTEM_SECURE
__set_PSR(0xc0000140);
#else
__set_PSR(0x80000140);
#endif
#endif
#ifdef CONFIG_LPM_TICKLESS_SLEEP
system_timer = csi_timer_initialize(CONFIG_LPM_TICKLESS_SYSTIM, (void *)systick_handler);
csi_timer_config(system_timer, TIMER_MODE_RELOAD);
csi_timer_set_timeout(system_timer, 10000000);
csi_timer_start(system_timer);
count_timer = csi_timer_initialize(CONFIG_LPM_TICKLESS_CNTTIM, NULL);
csi_timer_config(count_timer, TIMER_MODE_RELOAD);
csi_timer_set_timeout(count_timer, 0);
csi_timer_start(count_timer);
#else
csi_coret_config(SYSTEM_CLOCK / CONFIG_SYSTICK_HZ, CORET_IRQn); //10ms
#ifndef CONFIG_KERNEL_NONE
csi_vic_enable_irq(CORET_IRQn);
#endif
#endif
SystemCoreClock = SYSTEM_CLOCK;
#ifndef CONFIG_KERNEL_RHINO
#ifndef CONFIG_NUTTXMM_NONE
extern void mm_heap_initialize(void);
mm_heap_initialize();
#endif
#endif
}

View file

@ -0,0 +1,42 @@
/* ****************************************************************************
* *
* C-Sky Microsystems Confidential *
* ------------------------------- *
* This file and all its contents are properties of C-Sky Microsystems. The *
* information contained herein is confidential and proprietary and is not *
* to be disclosed outside of C-Sky Microsystems except under a *
* Non-Disclosured Agreement (NDA). *
* *
****************************************************************************/
#ifndef TEE_ADDR_MAP_H
#define TEE_ADDR_MAP_H
#include "partitions.h"
#ifndef PART_ADDR_TEE
#error "PART_ADDR_TEE undefined!"
#endif
#ifndef PART_SIZE_TEE
#error "PART_SIZE_TEE undefined!"
#endif
#define OTP_BANK_SIZE 2048
#define OTP_BASE_ADDR 0x4003f800//0x40006000
#define TW_RO_ADDR PART_ADDR_TEE //0x10005800
#define TW_RO_SIZE PART_SIZE_TEE
#define TW_RW_ADDR 0x60000000//0x20000000
#define TW_RW_SIZE 0x00001000
#define NTW_RO_ADDR 0x1000BC00
#define NTW_RO_SIZE 0x00010000
#define NTW_RW_ADDR (TW_RW_ADDR + 0x00002000)
#define NTW_RW_SIZE 0x00006000
#define SRAM_BASE_ADDR 0x60000000//0x20000000
#define NTW_ENTRY_ADDR NTW_RO_ADDR
#endif

View file

@ -0,0 +1,56 @@
/*
* Copyright (C) 2017 C-SKY Microsystems Co., Ltd. All rights reserved.
*
* 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 trap_c.c
* @brief source file for the trap process
* @version V1.0
* @date 12. December 2017
******************************************************************************/
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <csi_config.h>
void trap_c(uint32_t *regs)
{
int i;
uint32_t vec = 0;
asm volatile(
"mfcr %0, psr \n"
"lsri %0, 16 \n"
"sextb %0 \n"
:"=r"(vec):);
printf("CPU Exception : %d", vec);
printf("\n");
for (i = 0; i < 16; i++) {
printf("r%d: %08x\t", i, regs[i]);
if ((i % 5) == 4) {
printf("\n");
}
}
printf("\n");
printf("epsr: %8x\n", regs[16]);
printf("epc : %8x\n", regs[17]);
while (1);
}

View file

@ -0,0 +1,102 @@
/*
* Copyright (C) 2017 C-SKY Microsystems Co., Ltd. All rights reserved.
*
* 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 vectors.S
* @brief define default vector handlers. Should use with
* GCC for CSKY Embedded Processors
* @version V1.0
* @date 28. Nove 2017
******************************************************************************/
#include <csi_config.h>
.import trap_c
.text
/******************************************************************************
* Functions:
* void trap(void);
* default exception handler
******************************************************************************/
.global trap
.type trap, %function
trap:
psrset ee
mov r0, r0
subi sp, 72
stm r0-r13, (sp)
mov r0, sp
addi r0, 72
stw r0, (sp, 56)
stw r15, (sp, 60)
mfcr r0, epsr
stw r0, (sp, 64)
mfcr r0, epc
stw r0, (sp, 68)
mov r0, sp
/* for backtrace */
subi sp, 8
stw r8, (sp, 0)
stw r15, (sp, 4)
mov r8, sp
lrw r1, trap_c
jmp r1
.align 1
.weak Default_Handler
.type Default_Handler, %function
Default_Handler:
br trap
.size Default_Handler, . - Default_Handler
/* Macro to define default handlers. Default handler
* will be weak symbol and just dead loops. They can be
* overwritten by other handlers */
.macro def_irq_handler handler_name
.weak \handler_name
.globl \handler_name
.set \handler_name, Default_Handler
.endm
def_irq_handler CORET_IRQHandler
def_irq_handler TIMA0_IRQHandler
def_irq_handler TIMA1_IRQHandler
def_irq_handler TIMB0_IRQHandler
def_irq_handler TIMB1_IRQHandler
def_irq_handler USART0_IRQHandler
def_irq_handler USART1_IRQHandler
def_irq_handler USART2_IRQHandler
def_irq_handler USART3_IRQHandler
def_irq_handler GPIO0_IRQHandler
def_irq_handler GPIO1_IRQHandler
def_irq_handler I2C0_IRQHandler
def_irq_handler I2C1_IRQHandler
def_irq_handler SPI0_IRQHandler
def_irq_handler SPI1_IRQHandler
def_irq_handler RTC_IRQHandler
def_irq_handler RTC1_IRQHandler
def_irq_handler WDT_IRQHandler
def_irq_handler PWM_IRQHandler
def_irq_handler DMAC_IRQHandler
def_irq_handler AES_IRQHandler
def_irq_handler RSA_IRQHandler
def_irq_handler SHA_IRQHandler

View file

@ -0,0 +1,164 @@
/*
* Copyright (C) 2017 C-SKY Microsystems Co., Ltd. All rights reserved.
*
* 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_adc.h
* @brief Header File for ADC Driver
* @version V1.0
* @date 15. October 2017
******************************************************************************/
#ifndef _CSI_ADC_H_
#define _CSI_ADC_H_
#ifdef __cplusplus
extern "C" {
#endif
#include <stdint.h>
#include <drv_errno.h>
#include <drv_common.h>
/// definition for adc handle.
typedef void *adc_handle_t;
/****** ADC conversion mode *****/
typedef enum {
ADC_SINGLE = 0, ///< Single conversion mode --- select one channel to convert at a time.
ADC_CONTINUOUS, ///< Continuous conversion mode --- select a channel to convert in a specific times.
ADC_SCAN, ///< Scan mode --- select a group channel to convert at a time.
} adc_mode_e;
/****** ADC Event *****/
typedef enum {
ADC_EVENT_CONVERSION_COMPLETE = 0, ///< All data conversion completed.
ADC_EVENT_DATA_LOST, ///< Data lost: adc buffer overflow / transmit underflow.
ADC_EVENT_DATA_OVERWRITE, ///< Converted data has not been read before the new conversion result is load to the data register.
ADC_EVENT_DATA_COMPARE_VALID, ///< Data compare right with adc comparator.
} adc_event_e;
/****** ADC Status *****/
typedef struct {
uint32_t busy : 1; ///< adc conversion on going.
uint32_t data_lost : 1; ///< adc buffer overflow.
uint32_t complete : 1; ///< adc conversion completion.
uint32_t compare_valid : 1; ///< data valid through adc comparator.
} adc_status_t;
/**
\brief ADC Driver Capabilities.
*/
typedef struct {
uint32_t single : 1;
uint32_t continuous : 1;
uint32_t scan : 1;
uint32_t calibration : 1;
uint32_t comparator : 1;
} adc_capabilities_t;
typedef struct {
uint32_t clk_prescaler; ///< select ADC clock prescaler.
adc_mode_e mode; ///< \ref adc_mode_e
uint32_t trigger; ///< 0 -- software adc start or 1 -- external event trigger to start adc.
uint32_t intrp_mode; ///< specifies whether the ADC is configured is interrupt mode (1)or in polling mode (0).
uint32_t* channel_array; ///< channel array base address, the ordinal of channel count from zero, like ADC_CHANNEL0 (0), ADC_CHANNEL1(1), etc.
uint32_t channel_nbr; ///< specifies the number of channels in channel array that will be converted.
uint32_t conv_cnt; ///< conversion count times for conversion mode.
uint32_t sampling_time; ///< sampling time value to be set for the selected channel. Unit:ADC clock cycles.
uint32_t offset; ///< reserved for future use, can be set to 0.
} adc_conf_t;
typedef struct {
uint32_t cmp_data; ///< the data is used to compare with conversion result of specified channel.
uint32_t cmp_channel; ///< compare channel selection.
uint32_t cmp_condition; ///< compare condition: 0 = Set the compare condition as that when a A/D conversion result is less than the cmp_data. 1 = Set the compare condition as that when a A/D conversion result is greater or equal to the cmp_data.
uint32_t cmp_match_cnt; ///< when the specified A/D channel analog conversion result matches the compare condition defined by cmp_condition, the internal match counter will increase 1. When the internal counter reaches the value to (cpm_match_cnt), the correspond status or flag bit will be set.
} adc_cmp_conf_t;
typedef void (*adc_event_cb_t)(int32_t idx, adc_event_e event); ///< Pointer to \ref adc_event_cb_t : adc Event call back.
/**
\brief Initialize adc Interface. 1. Initializes the resources needed for the adc interface 2.registers event callback function.
\param[in] idx adc index.
\param[in] cb_event event call back function \ref adc_event_cb_t
\return return adc handle if success
*/
adc_handle_t csi_adc_initialize(int32_t idx, adc_event_cb_t cb_event);
/**
\brief De-initialize adc Interface. stops operation and releases the software resources used by the interface
\param[in] handle adc handle to operate.
\return error code
*/
int32_t csi_adc_uninitialize(adc_handle_t handle);
/**
\brief Get driver capabilities.
\param[in] idx adc index.
\return \ref adc_capabilities_t
*/
adc_capabilities_t csi_adc_get_capabilities(int32_t idx);
/**
\brief config adc mode.
\param[in] handle adc handle to operate.
\param[in] config adc_conf_t\ref . pointer to adc configuration structure.
\return error code
*/
int32_t csi_adc_config(adc_handle_t handle, adc_conf_t *config);
/**
\brief config adc comparator.
\param[in] handle adc handle to operate.
\param[in] config adc_conf_t\ref . pointer to adc configuration structure.
\return error code
*/
int32_t csi_adc_comparator_config(adc_handle_t handle, adc_cmp_conf_t *config);
/**
\brief start adc.
\param[in] handle adc handle to operate.
\return error code
*/
int32_t csi_adc_start(adc_handle_t handle);
/**
\brief stop adc.
\param[in] handle adc handle to operate.
\return error code
*/
int32_t csi_adc_stop(adc_handle_t handle);
/**
\brief receiving data from ADC receiver.
\param[in] handle ADC handle to operate.
\param[out] data Pointer to buffer for data to receive from ADC receiver, the data array is correspond to channel array.
\param[in] num Number of data items to receive.
\return error code
*/
int32_t csi_adc_read(adc_handle_t handle, uint32_t *data, uint32_t num);
/**
\brief Get ADC status.
\param[in] handle adc handle to operate.
\return ADC status \ref adc_status_t
*/
adc_status_t csi_adc_get_status(adc_handle_t handle);
#ifdef __cplusplus
}
#endif
#endif /* _CSI_ADC_H_ */

View file

@ -0,0 +1,253 @@
/*
* Copyright (C) 2017 C-SKY Microsystems Co., Ltd. All rights reserved.
*
* 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_aes.h
* @brief Header File for AES Driver
* @version V1.0
* @date 02. June 2017
******************************************************************************/
#ifndef _CSI_AES_H_
#define _CSI_AES_H_
#ifdef __cplusplus
extern "C" {
#endif
#include <stdint.h>
#include <drv_common.h>
#include <drv_errno.h>
/// definition for aes handle.
typedef void *aes_handle_t;
/****** AES specific error codes *****/
typedef enum {
AES_ERROR_MODE = (DRV_ERROR_SPECIFIC + 1) , ///< Specified Mode not supported
AES_ERROR_DATA_BITS , ///< Specified number of Data bits not supported
AES_ERROR_ENDIAN ///< Specified endian not supported
} aes_error_e;
/*----- AES Control Codes: Mode -----*/
typedef enum {
AES_MODE_ECB = 0, ///< ECB Mode
AES_MODE_CBC , ///< CBC Mode
AES_MODE_CFB1 , ///< CFB1 Mode
AES_MODE_CFB8 , ///< CFB8 Mode
AES_MODE_CFB128 , ///< CFB128 Mode
AES_MODE_OFB , ///< OFB Mode
AES_MODE_CTR ///< CTR Mode
} aes_mode_e;
/*----- AES Control Codes: Crypto Mode -----*/
typedef enum {
AES_CRYPTO_MODE_ENCRYPT = 0, ///< encrypt Mode
AES_CRYPTO_MODE_DECRYPT , ///< decrypt Mode
} aes_crypto_mode_e;
/*----- AES Control Codes: Mode Parameters: Key length -----*/
typedef enum {
AES_KEY_LEN_BITS_128 = 0, ///< 128 Data bits
AES_KEY_LEN_BITS_192 , ///< 192 Data bits
AES_KEY_LEN_BITS_256 ///< 256 Data bits
} aes_key_len_bits_e;
/*----- AES Control Codes: Mode Parameters: Endian -----*/
typedef enum {
AES_ENDIAN_LITTLE = 0, ///< Little Endian
AES_ENDIAN_BIG ///< Big Endian
} aes_endian_mode_e;
/**
\brief AES Status
*/
typedef struct {
uint32_t busy : 1; ///< busy flag
} aes_status_t;
/****** AES Event *****/
typedef enum {
AES_EVENT_CRYPTO_COMPLETE = 0 ///< Encrypt completed
} aes_event_e;
typedef void (*aes_event_cb_t)(int32_t idx, aes_event_e event); ///< Pointer to \ref aes_event_cb_t : AES Event call back.
/**
\brief AES Device Driver Capabilities.
*/
typedef struct {
uint32_t ecb_mode : 1; ///< supports ECB mode
uint32_t cbc_mode : 1; ///< supports CBC mode
uint32_t cfb1_mode : 1; ///< supports CFB1 mode
uint32_t cfb8_mode : 1; ///< supports CFB8 mode
uint32_t cfb128_mode : 1; ///< supports CFB128 mode
uint32_t ofb_mode : 1; ///< supports OFB mode
uint32_t ctr_mode : 1; ///< supports CTR mode
uint32_t bits_128 : 1; ///< supports 128bits key length
uint32_t bits_192 : 1; ///< supports 192bits key length
uint32_t bits_256 : 1; ///< supports 256bits key length
} aes_capabilities_t;
// Function documentation
/**
\brief Initialize AES Interface. 1. Initializes the resources needed for the AES interface 2.registers event callback function
\param[in] idx index of aes
\param[in] cb_event Pointer to \ref aes_event_cb_t
\return return aes handle if success
*/
aes_handle_t csi_aes_initialize(int32_t idx, aes_event_cb_t cb_event);
/**
\brief De-initialize AES Interface. stops operation and releases the software resources used by the interface
\param[in] handle aes handle to operate.
\return error code
*/
int32_t csi_aes_uninitialize(aes_handle_t handle);
/**
\brief Get driver capabilities.
\param[in] idx device id
\return \ref aes_capabilities_t
*/
aes_capabilities_t csi_aes_get_capabilities(int32_t idx);
/**
\brief config aes mode.
\param[in] handle aes handle to operate.
\param[in] mode \ref aes_mode_e
\param[in] keylen_bits \ref aes_key_len_bits_e
\param[in] endian \ref aes_endian_mode_e
\return error code
*/
int32_t csi_aes_config(aes_handle_t handle,
aes_mode_e mode,
aes_key_len_bits_e keylen_bits,
aes_endian_mode_e endian
);
/**
\brief set crypto key.
\param[in] handle aes handle to operate.
\param[in] context aes information context(NULL when hardware implementation)
\param[in] key Pointer to the key buf
\param[in] key_len Pointer to \ref aes_key_len_bits_e
\param[in] enc \ref aes_crypto_mode_e
\return error code
*/
int32_t csi_aes_set_key(aes_handle_t handle, void *context, void *key, aes_key_len_bits_e key_len, aes_crypto_mode_e enc);
/**
\brief aes ecb encrypt or decrypt
\param[in] handle aes handle to operate.
\param[in] context aes information context(NULL when hardware implementation)
\param[in] in Pointer to the Source data
\param[out] out Pointer to the Result data.
\param[in] len the Source data len.
\return error code
*/
int32_t csi_aes_ecb_crypto(aes_handle_t handle, void *context, void *in, void *out, uint32_t len);
/**
\brief aes cbc encrypt or decrypt
\param[in] handle aes handle to operate.
\param[in] context aes information context(NULL when hardware implementation)
\param[in] in Pointer to the Source data
\param[out] out Pointer to the Result data.
\param[in] len the Source data len.
\param[in] iv Pointer to initialization vector(updated after use)
\return error code
*/
int32_t csi_aes_cbc_crypto(aes_handle_t handle, void *context, void *in, void *out, uint32_t len, unsigned char iv[16]);
/**
\brief aes cfb1 encrypt or decrypt
\param[in] handle aes handle to operate.
\param[in] context aes information context(NULL when hardware implementation)
\param[in] in Pointer to the Source data
\param[out] out Pointer to the Result data.
\param[in] len the Source data len.
\param[in] iv Pointer to initialization vector(updated after use)
\return error code
*/
int32_t csi_aes_cfb1_crypto(aes_handle_t handle, void *context, void *in, void *out, uint32_t len, unsigned char iv[16]);
/**
\brief aes cfb8 encrypt or decrypt
\param[in] handle aes handle to operate.
\param[in] context aes information context(NULL when hardware implementation)
\param[in] in Pointer to the Source data
\param[out] out Pointer to the Result data.
\param[in] len the Source data len.
\param[in] iv Pointer to initialization vector(updated after use)
\return error code
*/
int32_t csi_aes_cfb8_crypto(aes_handle_t handle, void *context, void *in, void *out, uint32_t len, unsigned char iv[16]);
/**
\brief aes cfb128 encrypt or decrypt
\param[in] handle aes handle to operate.
\param[in] context aes information context(NULL when hardware implementation)
\param[in] in Pointer to the Source data
\param[out] out Pointer to the Result data.
\param[in] len the Source data len.
\param[in] iv Pointer to initialization vector(updated after use)
\param[in] num the number of the 128-bit block we have used(updated after use)
\return error code
*/
int32_t csi_aes_cfb128_crypto(aes_handle_t handle, void *context, void *in, void *out, uint32_t len, unsigned char iv[16], uint32_t *num);
/**
\brief aes ofb encrypt or decrypt
\param[in] handle aes handle to operate.
\param[in] context aes information context(NULL when hardware implementation)
\param[in] in Pointer to the Source data
\param[out] out Pointer to the Result data.
\param[in] len the Source data len.
\param[in] iv Pointer to initialization vector(updated after use)
\param[in] num the number of the 128-bit block we have used(updated after use)
\return error code
*/
int32_t csi_aes_ofb_crypto(aes_handle_t handle, void *context, void *in, void *out, uint32_t len, unsigned char iv[16], uint32_t *num);
/**
\brief aes ofb encrypt or decrypt
\param[in] handle aes handle to operate.
\param[in] context aes information context(NULL when hardware implementation)
\param[in] in Pointer to the Source data
\param[out] out Pointer to the Result data.
\param[in] len the Source data len.
\param[in] nonce_counter Pointer to the 128-bit nonce and counter(updated after use)
\param[in] stream_block Pointer to the saved stream-block for resuming(updated after use)
\param[in] num the number of the 128-bit block we have used(updated after use)
\return error code
*/
int32_t csi_aes_ctr_crypto(aes_handle_t handle, void *context, void *in, void *out, uint32_t len, unsigned char nonce_counter[16], unsigned char stream_block[16], uint32_t *num);
/**
\brief Get AES status.
\param[in] handle aes handle to operate.
\return AES status \ref aes_status_t
*/
aes_status_t csi_aes_get_status(aes_handle_t handle);
#ifdef __cplusplus
}
#endif
#endif /* _CSI_AES_H_ */

View file

@ -0,0 +1,440 @@
/*
* Copyright (C) 2017 C-SKY Microsystems Co., Ltd. All rights reserved.
*
* 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_bmu.h
* @brief header file for bmu driver
* @version V1.0
* @date 02. June 2017
******************************************************************************/
#ifndef _CSI_BMU_H_
#define _CSI_BMU_H_
#ifdef __cplusplus
extern "C" {
#endif
#include <drv_common.h>
#include <drv_pmu.h>
/// definition for bmu handle.
typedef void *bmu_handle_t;
typedef enum {
BUCK_LS0 = 0, /*run/dor/sby onoff*/
BUCK_LS1 = 1, /*run/dor/sby onoff*/
HVIOLDO = 2, /*run/dor/sby onoff*/ /*run/dor/sby prog BW3*/
LVIOLDO = 3, /*run/dor/sby onoff*/ /*run/dor/sby prog BW3*/
ABB_LS = 4, /*run/dor/sby onoff*/
HVIO_LS = 5, /*run/dor/sby onoff*/
ACORELDO = 6, /*run/dor sby onoff*/
SIMLDO = 7, /*run/dor/sby onoff*/ /*run/dor/sby prog BW3*/
ANALDO = 8, /*run/dor/sby onoff*/
LPCORELDO = 9, /* dor/sby onoff*/
MCORELDO = 10, /* dor/sby onoff*/
MAINBGP = 11, /* dor/sby onoff*/
BUCKDC = 12, /* dor/sby onoff*/ /*run/dor/sby prog BW8*/
CORELDO = 13, /*run/dor/sby prog BW4*/
} bmu_regulator_e;
typedef enum {
DISABLE = 0,
ENABLE = 1,
}bmu_enable_e;
typedef enum {
HVIOLDO_1_800 = 0,
HVIOLDO_2_500 = 1,
HVIOLDO_2_700 = 2,
HVIOLDO_2_850 = 3,/*default*/
HVIOLDO_3_000 = 4,
HVIOLDO_3_300 = 5,
} bmu_hvioldo_vol_e;
typedef enum {
LVIOLDO_1_600 = 0,
LVIOLDO_1_640 = 1,
LVIOLDO_1_680 = 2,
LVIOLDO_1_720 = 3,
LVIOLDO_1_760 = 4,
LVIOLDO_1_800 = 5,/*default*/
LVIOLDO_1_840 = 6,
LVIOLDO_1_880 = 7,
} bmu_lvioldo_vol_e;
typedef enum {
SIMLDO_1_800 = 0,/*default*/
SIMLDO_2_500 = 1,
SIMLDO_2_700 = 2,
SIMLDO_2_850 = 3,
SIMLDO_3_000 = 4,
SIMLDO_3_300 = 5,
} bmu_simldo_vol_e;
typedef enum {
BUCKDC_1_500 = 0,
BUCKDC_1_620 = 4,
BUCKDC_1_740 = 8,
BUCKDC_1_800 = 10,
BUCKDC_1_830 = 11,
BUCKDC_1_860 = 12,
BUCKDC_1_950 = 15,
} bmu_buckdc_vol_e;
typedef enum {
CORELDO_0_900 = 0,
CORELDO_1_020 = 4,
CORELDO_1_110 = 7,
CORELDO_1_200 = 10,/*default*/
} bmu_coreldo_vol_e;
typedef enum {
ANALDO_2_000 = 0,
ANALDO_2_500 = 1,
ANALDO_2_700 = 2,
ANALDO_2_850 = 3,
ANALDO_3_000 = 4,
ANALDO_3_300 = 5,/*default*/
} bmu_analdo_vol_e;
typedef enum {
SBYLDO_1_640 = 0,
SBYLDO_1_680 = 1,
SBYLDO_1_720 = 2,
SBYLDO_1_760 = 3,
SBYLDO_1_800 = 4,
SBYLDO_1_840 = 5,/*default*/
SBYLDO_1_880 = 6,
SBYLDO_1_920 = 7,
} bmu_sbyldo_vol_e;
typedef enum {
SDNPVD_2_200 = 0,/*default*/
SDNPVD_2_400 = 1,
SDNPVD_2_600 = 2,
SDNPVD_2_800 = 3,
SDNPVD_3_000 = 4,
SDNPVD_3_200 = 5,
SDNPVD_3_400 = 6,
SDNPVD_3_600 = 7,
} bmu_sdnpvd_vol_e;
typedef enum {
SDNBOR_1_800 = 0,
SDNBOR_2_000 = 1,/*default*/
SDNBOR_2_200 = 2,
SDNBOR_2_500 = 3,
SDNBOR_2_800 = 4,
SDNBOR_3_000 = 5,
SDNBOR_3_100 = 6,
SDNBOR_3_200 = 7,
} bmu_sdnbor_vol_e;
typedef enum {
SDNCMP_9uA = 0,/*default*/
SDNCMP_11uA = 1,
SDNCMP_16uA = 2,
SDNCMP_30uA = 3,
} bmu_sdncmp_cur_e;
typedef enum {
MAINBGP_0_720 = 0,
MAINBGP_0_730 = 1,
MAINBGP_0_740 = 2,
MAINBGP_0_750 = 3,
MAINBGP_0_760 = 4,
MAINBGP_0_770 = 5,
MAINBGP_0_780 = 6,
MAINBGP_0_790 = 7,
MAINBGP_0_800 = 8,/*default*/
MAINBGP_0_810 = 9,
MAINBGP_0_820 = 10,
MAINBGP_0_830 = 11,
MAINBGP_0_840 = 12,
MAINBGP_0_850 = 13,
MAINBGP_0_860 = 14,
MAINBGP_0_870 = 15,
} bmu_mainbgp_vol_e;
typedef enum {
SDNBGP_LPMODE_1_137 = 0,
SDNBGP_LPMODE_1_158 = 1,
SDNBGP_LPMODE_1_175 = 2,
SDNBGP_LPMODE_1_194 = 3,
SDNBGP_LPMODE_1_214 = 4,/*default*/
SDNBGP_LPMODE_1_233 = 5,
SDNBGP_LPMODE_1_252 = 6,
SDNBGP_LPMODE_1_271 = 7,
} bmu_sdnbgp_lpmode_vol_e;
typedef enum {
SDNBGP_HPMODE_1_152 = 0,
SDNBGP_HPMODE_1_171 = 1,
SDNBGP_HPMODE_1_191 = 2,
SDNBGP_HPMODE_1_210 = 3,
SDNBGP_HPMODE_1_230 = 4,/*default*/
SDNBGP_HPMODE_1_251 = 5,
SDNBGP_HPMODE_1_270 = 6,
SDNBGP_HPMODE_1_289 = 7,
} bmu_sdnbgp_hpmode_vol_e;
typedef enum {
VBAT = 0,/*default*/
PVD_IN = 1,
} bmu_pvdsel_5V_e;
typedef enum {
LLP_SHUTDOWN = 0,/*default*/
LLP_RESTART = 1,
} bmu_llp_todo_e;
typedef enum {
PSHOLD_DOWN = 0,/*default*/
PSHOLD_UP = 1,
} bmu_pshold_status_e;
/****** BMU Event *****/
typedef enum {
BMU_EVENT_SEND_COMPLETE = 0, ///< Send completed; however BMU may still transmit data
BMU_EVENT_RECEIVE_COMPLETE = 1, ///< Receive completed
BMU_EVENT_RECEIVED = 2, ///< Receiving data
BMU_EVENT_TRANSFER_COMPLETE = 3, ///< Transfer completed
BMU_EVENT_TX_COMPLETE = 4, ///< Transmit completed (optional)
BMU_EVENT_TX_UNDERFLOW = 5, ///< Transmit data not available (Synchronous Slave)
BMU_EVENT_RX_OVERFLOW = 6, ///< Receive data overflow
BMU_EVENT_RX_TIMEOUT = 7, ///< Receive character timeout (optional)
BMU_EVENT_RX_BREAK = 8, ///< Break detected on receive
BMU_EVENT_RX_FRAMING_ERROR = 9, ///< Framing error detected on receive
BMU_EVENT_RX_PARITY_ERROR = 10, ///< Parity error detected on receive
} bmu_event_e;
typedef void (*bmu_event_cb_t)(int32_t idx, bmu_event_e event); ///< Pointer to \ref bmu_event_cb_t : BMU Event call back.
/**
\brief BMU Driver Capabilities.
*/
typedef struct {
uint32_t asynchronous : 1; ///< supports BMU (Asynchronous) mode
uint32_t synchronous_master : 1; ///< supports Synchronous Master mode
uint32_t synchronous_slave : 1; ///< supports Synchronous Slave mode
uint32_t single_wire : 1; ///< supports BMU Single-wire mode
uint32_t event_tx_complete : 1; ///< Transmit completed event
uint32_t event_rx_timeout : 1; ///< Signal receive character timeout event
} bmu_capabilities_t;
/**
\brief Initialize BMU Interface. 1. Initializes the resources needed for the BMU interface 2.registers event callback function
\param[in] idx bmu id
\param[in] cb_event Pointer to \ref bmu_event_cb_t
\return return bmu handle if success
*/
bmu_handle_t csi_bmu_initialize(int32_t idx, bmu_event_cb_t cb_event);
/**
\brief De-initialize BMU Interface. stops operation and releases the software resources used by the interface
\param[in] handle bmu handle to operate.
\return error code
*/
int32_t csi_bmu_uninitialize(bmu_handle_t handle);
/**
\brief Get driver capabilities.
\param[in] handle bmu handle to operate.
\return \ref bmu_capabilities_t
*/
bmu_capabilities_t csi_bmu_get_capabilities(bmu_handle_t handle);
/**
* Pull pshold up or down.
*
* @param[in] enable Flag of up or down.
* @return none
*/
int32_t csi_bmu_set_pshold(bmu_handle_t handle, bmu_pshold_status_e enable);
/**
* Set key long long press to do.
*
* @param[in] enable Flag of shutdown or restart.
* @return none
*/
int32_t csi_bmu_set_llp_todo(bmu_handle_t handle, bmu_llp_todo_e enable);
/**
* Set mainbgp voltage.
*
* @param[in] mainbgp_vol Voltage of Regulator.
* @return none
*/
int32_t csi_bmu_mainbgp_setvol(bmu_handle_t handle, bmu_mainbgp_vol_e mainbgp_vol);
/**
* Set sdnbgp voltage in lpmode.
*
* @param[in] vol Voltage of sdnbgp in lpmode.
* @return none
*/
int32_t csi_bmu_sdnbgp_lpmode_setvol(bmu_handle_t handle, bmu_sdnbgp_lpmode_vol_e vol);
/**
* Set sdnbgp voltage in hpmode.
*
* @param[in] vol Voltage of sdnbgp in hpmode.
* @return none
*/
int32_t csi_bmu_sdnbgp_hpmode_setvol(bmu_handle_t handle, bmu_sdnbgp_hpmode_vol_e vol);
/**
* Set sdnpvd voltage.
*
* @param[in] sdnpvd_vol Voltage of sdnpvd.
* @return none
*/
int32_t csi_bmu_sdnpvd_setvol(bmu_handle_t handle, bmu_sdnpvd_vol_e sdnpvd_vol);
/**
* Set sdnpvd on or off.
*
* @param[in] enable Flag of enable or disable.
* @return none
*/
int32_t csi_bmu_sdnpvd_setonoff(bmu_handle_t handle, bmu_enable_e enable);
/**
* Select sdnpvd source.
*
* @param[in] enable Flag of sdnpvd source.
* @return none
*/
int32_t csi_bmu_sdnpvd_selsrc(bmu_handle_t handle, bmu_pvdsel_5V_e pvdsel);
/**
* Set sdnbor voltage.
*
* @param[in] sdnbor_vol Voltage of sdnbor.
* @return none
*/
int32_t csi_bmu_sdnbor_setvol(bmu_handle_t handle, bmu_sdnbor_vol_e sdnbor_vol);
/**
* Set sdncmp current.
*
* @param[in] sdncmp_cur Current of sdncmp.
* @return none
*/
int32_t csi_bmu_sdncmp_setcur(bmu_handle_t handle, bmu_sdncmp_cur_e sdncmp_cur);
/**
* Set sdncmp on or off.
*
* @param[in] enable Flag of enable or disable.
* @return none
*/
int32_t csi_bmu_sdncmp_setonoff(bmu_handle_t handle, bmu_enable_e enable);
/**
* Set hvioldo voltage in different bmu mod.
*
* @param[in] pmu_mode Pmu mode.
* @param[in] hvioldo Voltage value.
* @return 0 is OK, others is error
*/
int32_t csi_bmu_hvioldo_setvol(bmu_handle_t handle, pmu_mode_e pmu_mode, bmu_hvioldo_vol_e hvioldo_vol);
/**
* Set simldo voltage in different bmu mod.
*
* @param[in] pmu_mode Pmu mode.
* @param[in] simldo Voltage value.
* @return 0 is OK, others is error
*/
int32_t csi_bmu_simldo_setvol(bmu_handle_t handle, pmu_mode_e pmu_mode, bmu_simldo_vol_e simldo_vol);
/**
* Set buckdc voltage in different bmu mod.
*
* @param[in] pmu_mode Pmu mode.
* @param[in] buckdc Voltage value.
* @return 0 is OK, others is error
*/
int32_t csi_bmu_buckdc_setvol(bmu_handle_t handle, pmu_mode_e pmu_mode, bmu_buckdc_vol_e buckdc_vol);
/**
* Set coreldo voltage in different bmu mod.
*
* @param[in] pmu_mode Pmu mode.
* @param[in] coreldo Voltage value.
* @return 0 is OK, others is error
*/
int32_t csi_bmu_coreldo_setvol(bmu_handle_t handle, pmu_mode_e pmu_mode, bmu_coreldo_vol_e coreldo_vol);
/**
* Set lvioldo voltage in different bmu mod.
*
* @param[in] pmu_mode Pmu mode.
* @param[in] lvioldo Voltage value.
* @return 0 is OK, others is error
*/
int32_t csi_bmu_lvioldo_setvol(bmu_handle_t handle, pmu_mode_e pmu_mode, bmu_lvioldo_vol_e lvioldo_vol);
/**
* Set analdo voltage.
*
* @param[in] analdo Voltage value.
* @return 0 is OK, others is error
*/
int32_t csi_bmu_analdo_setvol(bmu_handle_t handle, bmu_analdo_vol_e analdo_vol);
/**
* Set sbyldo voltage.
*
* @param[in] sbyldo Voltage value.
* @return 0 is OK, others is error
*/
int32_t csi_bmu_sbyldo_setvol(bmu_handle_t handle, bmu_sbyldo_vol_e sbyldo_vol);
/**
* Set regulator on or off in run mode of bmu.
*
* @param[in] regulator Identify of Regulator.
* @param[in] enable Flag of on or off.
* @return 0 is OK, others is error
*/
int32_t csi_bmu_run_setonoff(bmu_handle_t handle, bmu_regulator_e regulator, bmu_enable_e enable);
/**
* Set regulator on or off in dormant mode of bmu.
*
* @param[in] regulator Identify of Regulator.
* @param[in] enable Flag of on or off.
* @return 0 is OK, others is error
*/
int32_t csi_bmu_dor_setonoff(bmu_handle_t handle, bmu_regulator_e regulator, bmu_enable_e enable);
/**
* Set regulator on or off in standby mode of bmu.
*
* @param[in] regulator Identify of Regulator.
* @param[in] enable Flag of on or off.
* @return 0 is OK, others is error
*/
int32_t csi_bmu_sby_setonoff(bmu_handle_t handle, bmu_regulator_e regulator, bmu_enable_e enable);
#ifdef __cplusplus
}
#endif
#endif /* _CSI_BMU_H_ */

View file

@ -0,0 +1,182 @@
/*
* Copyright (C) 2017 C-SKY Microsystems Co., Ltd. All rights reserved.
*
* 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_clk.h
* @brief header file for clk driver
* @version V1.0
* @date 02. June 2017
******************************************************************************/
#ifndef _CSI_CLK_H_
#define _CSI_CLK_H_
#ifdef __cplusplus
extern "C" {
#endif
#include <drv_common.h>
typedef enum {
CK_TIMER0_PCLK,
CK_TIMER1_PCLK,
CK_TIMER0_WCLK,
CK_TIMER1_WCLK,
AP_WDT_PCLK,
AP_WDT_WCLK,
AP_IRAM1_IROM_CLK,
AP_IRAM2_CLK,
UART0_PCLK,
UART1_PCLK,
UART2_PCLK,
LP_UART_PCLK,
UART0_WCLK_L1,
UART0_WCLK_L2,
UART1_WCLK,
UART2_WCLK,
LP_UART_WCLK,
I2C0_PCLK,
I2C1_PCLK,
I2C0_WCLK,
I2C1_WCLK,
SSP0_PCLK,
SSP1_PCLK,
SSP2_PCLK,
SSP0_WCLK,
SSP1_WCLK,
SSP2_WCLK,
GPIO_PD_PCLK,
ADC_PCLK,
ADC_WCLK,
DAC_PCLK,
DAC_WCLK,
AD_TIMER0_PCLK,
AD_TIMER1_PCLK,
AD_TIMER0_WCLK,
AD_TIMER1_WCLK,
AP_DMA_PCLK,
LP_TIMER_PCLK,
LP_TIMER_WCLK,
} clk_name;
/*
* bits domain definition for clock frequency
* base clock name same clock number reserved clock selection frequency division
* 31...28 27...24 23...20 19...16 15...12 11...8 7...4 3...0
* invalid value:
* 0xff 0xf or 0x0 0x0 or ignore 0xff 0xff
*/
typedef enum
{
FIXED_FREQ = 0xffffffff,
/*ck timer0&1/rm timer0&1/ceva timer0&1*/
WCLK_TIMER_32K = (CK_TIMER0_WCLK << 24) | 0x00600000,
WCLK_TIMER_19M2 = (CK_TIMER0_WCLK << 24) | 0x06000100, /* 1 div*/
WCLK_TIMER_9M6 = (CK_TIMER0_WCLK << 24) | 0x00600101, /* 2 div*/
/*ap wdt/cp wdt*/
WCLK_WDT_32K = (AP_WDT_WCLK << 24) | 0x00200000,
WCLK_WDT_19M2 = (AP_WDT_WCLK << 24) | 0x00200100,
WCLK_WDT_9M6 = (AP_WDT_WCLK << 24) | 0x00200101,
/*i2c0&1*/
WCLK_I2C_76M8 = (I2C0_WCLK << 24) | 0x00200100,
WCLK_I2C_19M2 = (I2C0_WCLK << 24) | 0x00200000,
/*uart0&1&2&lp uart*/
WCLK_UART_19M2 = (UART0_WCLK_L1 << 24) | 0x00400000,
WCLK_UART_76M8 = (UART0_WCLK_L1 << 24) | 0x00400100,
/*only for uart0& lp uart*/
WCLK_UART_32K = (UART0_WCLK_L1 << 24) | 0x00400200,
/*ssp0&1&2*/
WCLK_SSP_19M2 = (SSP0_WCLK << 24) | 0x00300000,
WCLK_SSP_76M8 = (SSP0_WCLK << 24) | 0x00300100,
WCLK_SSP_61m44 = (SSP0_WCLK << 24) | 0x00300200,
/*adc*/
WCLK_ADC_19M2 = (ADC_WCLK <<24) | 0x00100000,
WCLK_ADC_38M4 = (ADC_WCLK <<24) | 0x00100100,
WCLK_ADC_61M44 = (ADC_WCLK <<24) | 0x00100200,
WCLK_ADC_32K = (ADC_WCLK <<24) | 0x00100300,
/*dac*/
WCLK_DAC_19M2 = (DAC_WCLK <<24) | 0x001001000,
WCLK_DAC_32K = (DAC_WCLK <<24) | 0x00100200,
/*ad timer0&1*/
WCLK_AD_TIMER_32K = (AD_TIMER0_WCLK <<24) | 0x002000000,
WCLK_AD_TIMER_76M8 = (AD_TIMER0_WCLK <<24) | 0x00200100,
WCLK_AD_TIMER_19M2 = (AD_TIMER0_WCLK <<24) | 0x00200200,
/*lp timer*/
WCLK_LP_TIMER_32K = (LP_TIMER_WCLK <<24) | 0x001000000,
WCLK_LP_TIMER_76M8 = (LP_TIMER_WCLK <<24) | 0x001000100,
WCLK_LP_TIMER_19M2 = (LP_TIMER_WCLK <<24) | 0x001000200,
} clk_freq_sel;
/**
\brief set software clock gate.
\param[in] name the clock name to set.
\param[in] ctrl 0 enable; 1 disable
\return error code
*/
int csi_clk_sw_gate_ctrl(clk_name name, uint32_t ctrl);
/**
\brief set clock autogate.
\param[in] name the clock name to set.
\param[in] ctrl 0 enable; 1 disable
\return error code
*/
int csi_clk_hw_gate_ctrl(clk_name name, uint32_t ctrl);
/**
\brief config clock reset ctrl.
\param[in] name the clock name to set.
\param[in] ctrl 0 enable; 1 disable
\return error code
*/
int csi_clk_reset(clk_name name, uint32_t ctrl);
/**
\brief set clock freq.
\param[in] name the clock name to set.
\param[in] freq teh corresponding freq to set
\return error code
*/
int csi_clk_set_freq(clk_name name, clk_freq_sel freq);
#ifdef __cplusplus
}
#endif
#endif /* _CSI_CLK_H_ */

View file

@ -0,0 +1,43 @@
/*
* Copyright (C) 2017 C-SKY Microsystems Co., Ltd. All rights reserved.
*
* 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_common.h
* @brief Header File for Common Driver
* @version V1.0
* @date 02. June 2017
******************************************************************************/
#ifndef _DRV_COMMON_H_
#define _DRV_COMMON_H_
#include <stdint.h>
#include <drv_errno.h>
/// \details driver handle
typedef void *drv_handle_t;
/**
\brief General power states
*/
typedef enum {
DRV_POWER_OFF, ///< Power off: no operation possible
DRV_POWER_LOW, ///< Low Power mode: retain state, detect and signal wake-up events
DRV_POWER_FULL ///< Power on: full operation at maximum performance
} csi_power_stat_e;
#endif /* _DRV_COMMON_H */

View file

@ -0,0 +1,144 @@
/*
* Copyright (C) 2017 C-SKY Microsystems Co., Ltd. All rights reserved.
*
* 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_crc.h
* @brief Header File for CRC Driver
* @version V1.0
* @date 02. June 2017
******************************************************************************/
#ifndef _CSI_CRC_H_
#define _CSI_CRC_H_
#ifdef __cplusplus
extern "C" {
#endif
#include <stdint.h>
#include <drv_errno.h>
#include <drv_common.h>
/****** CRC specific error codes *****/
#define CRC_ERROR_MODE (DRV_ERROR_SPECIFIC + 1) ///< Specified Mode not supported
/// definition for crc handle.
typedef void *crc_handle_t;
/*----- CRC Control Codes: Mode -----*/
typedef enum {
CRC_MODE_CRC8 = 0, ///< Mode CRC8
CRC_MODE_CRC16 , ///< Mode CRC16
CRC_MODE_CRC32 ///< Mode CRC32
} crc_mode_e;
/*----- CRC Control Codes: Mode Parameters: Key length -----*/
typedef enum {
CRC_STANDARD_CRC_ROHC = 0, ///< Standard CRC RHOC
CRC_STANDARD_CRC_MAXIM , ///< Standard CRC MAXIAM
CRC_STANDARD_CRC_X25 , ///< Standard CRC X25
CRC_STANDARD_CRC_CCITT , ///< Standard CRC CCITT
CRC_STANDARD_CRC_USB , ///< Standard CRC USB
CRC_STANDARD_CRC_IBM , ///< Standard CRC IBM
CRC_STANDARD_CRC_MODBUS ///< Standard CRC MODBUS
} crc_standard_crc_e;
/**
\brief CRC Status
*/
typedef struct {
uint32_t busy : 1; ///< busy flag
} crc_status_t;
/****** CRC Event *****/
typedef enum {
CRC_EVENT_CALCULATE_COMPLETE = 0, ///< Calculate completed
} crc_event_e;
typedef void (*crc_event_cb_t)(int32_t idx, crc_event_e event); ///< Pointer to \ref crc_event_cb_t : CRC Event call back.
/**
\brief CRC Device Driver Capabilities.
*/
typedef struct {
uint32_t ROHC : 1; ///< supports ROHC mode
uint32_t MAXIM : 1; ///< supports MAXIM mode
uint32_t X25 : 1; ///< supports X25 mode
uint32_t CCITT : 1; ///< supports CCITT mode
uint32_t USB : 1; ///< supports USB mode
uint32_t IBM : 1; ///< supports IBM mode
uint32_t MODBUS : 1; ///< supports MODBUS mode
} crc_capabilities_t;
// Function documentation
/**
\brief Initialize CRC Interface. 1. Initializes the resources needed for the CRC interface 2.registers event callback function
\param[in] idx device id
\param[in] cb_event Pointer to \ref crc_event_cb_t
\return return crc handle if success
*/
crc_handle_t csi_crc_initialize(int32_t idx, crc_event_cb_t cb_event);
/**
\brief De-initialize CRC Interface. stops operation and releases the software resources used by the interface
\param[in] handle crc handle to operate.
\return error code
*/
int32_t csi_crc_uninitialize(crc_handle_t handle);
/**
\brief Get driver capabilities.
\param[in] idx device id
\return \ref crc_capabilities_t
*/
crc_capabilities_t csi_crc_get_capabilities(int32_t idx);
/**
\brief config crc mode.
\param[in] handle crc handle to operate.
\param[in] mode \ref crc_mode_e
\param[in] standard \ref crc_standard_crc_e
\return error code
*/
int32_t csi_crc_config(crc_handle_t handle,
crc_mode_e mode,
crc_standard_crc_e standard
);
/**
\brief calculate crc.
\param[in] handle crc handle to operate.
\param[in] in Pointer to the input data
\param[out] out Pointer to the result.
\param[in] len intpu data len.
\return error code
*/
int32_t csi_crc_calculate(crc_handle_t handle, const void *in, void *out, uint32_t len);
/**
\brief Get CRC status.
\param[in] handle crc handle to operate.
\return CRC status \ref crc_status_t
*/
crc_status_t csi_crc_get_status(crc_handle_t handle);
#ifdef __cplusplus
}
#endif
#endif /* _CSI_CRC_H_ */

View file

@ -0,0 +1,197 @@
/*
* Copyright (C) 2017 C-SKY Microsystems Co., Ltd. All rights reserved.
*
* 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_dmac.h
* @brief header file for dmac driver
* @version V1.0
* @date 02. June 2017
******************************************************************************/
#ifndef _CSI_DMA_H_
#define _CSI_DMA_H_
#ifdef __cplusplus
extern "C" {
#endif
#include <stdint.h>
#include <drv_common.h>
/// definition for dmac handle.
typedef void *dmac_handle_t;
/**
\brief DMA Driver Capabilities.
*/
typedef struct {
uint32_t unalign_addr : 1; ///< support for unalign address transfer when memory is source
} dma_capabilities_t;
typedef enum {
DMA_STATE_FREE = 0, ///< DMA not yet initialized or disabled
DMA_STATE_READY, ///< DMA process success and ready for use, but not start yet
DMA_STATE_BUSY, ///< DMA process is ongoing
DMA_STATE_ERROR, ///< DMA transfer error
DMA_STATE_DONE, ///< DMA transfer done
} dma_status_e;
/****** DMA specific error codes *****/
typedef enum {
EDRV_DMA_MODE = (DRV_ERROR_SPECIFIC + 1), ///< Specified Mode not supported
} dma_error_e;
/****** DMA Event *****/
typedef enum {
DMA_EVENT_TRANSFER_DONE = 0, ///< transfer complete
DMA_EVENT_TRANSFER_HALF_DONE = 1, ///< transfer half done
DMA_EVENT_TRANSFER_MODE_DONE = 2, ///< transfer complete in a certain dma trigger mode.
DMA_EVENT_CAHNNEL_PEND = 3, ///< it happens when there is a low priority channel was preempted by a high priority channel
DMA_EVENT_TRANSFER_ERROR = 4, ///< transfer error
} dma_event_e;
typedef enum {
DMA_ADDR_INC = 0,
DMA_ADDR_DEC,
DMA_ADDR_CONSTANT
} dma_addr_inc_e;
typedef enum {
DMA_MEM2MEM = 0,
DMA_MEM2PERH,
DMA_PERH2MEM,
DMA_PERH2PERH,
} dma_trans_type_e;
typedef enum {
SINGLE_TRIGGER = 0,
GROUP_TRIGGER,
BLOCK_TRIGGER
} dma_trig_trans_mode_e;
typedef enum {
DEST = 0,
SOURCE
} dma_single_dir_e;
typedef enum {
LITTLE = 0,
BIG
} dma_addr_endian_e;
typedef enum {
HARDWARE = 0,
SOFTWARE
} dma_channel_req_mode_e;
typedef struct {
dma_addr_inc_e src_inc; ///< source address increment
dma_addr_inc_e dst_inc; ///< destination address increment
dma_addr_endian_e src_endian; ///< source read data little-big endian change control.
dma_addr_endian_e dst_endian; ///< destination write data little-big endian change control.
uint8_t src_tw; ///< source transfer width in byte
uint8_t dst_tw; ///< destination transfer width in byte
uint32_t group_len; ///< group transaction length (unit: bytes) when use GROUP_TRIGGER mode.
uint8_t hs_if; ///< a hardware handshaking interface (option).
dma_trans_type_e type; ///< transfer type
dma_trig_trans_mode_e mode; ///< channel trigger mode
dma_channel_req_mode_e ch_mode; ///< software or hardware to tigger dma channel work.
dma_single_dir_e single_dir; ///< after select single mode control for source(read) or destination(write) transfer.
uint8_t preemption; ///< determine whether if a channel can be preempted by a higher priority channel, 0 -- not allow preempt, 1 -- allow preempt.
} dma_config_t;
typedef void (*dma_event_cb_t)(int32_t ch, dma_event_e event); ///< Pointer to \ref dma_event_cb_t : dmac event call back.
/**
\brief Initialize DMA Interface. 1. Initializes the resources needed for the DMA interface 2.registers event callback function
\param[in] dmac idx
\return pointer to dma instances
*/
dmac_handle_t csi_dma_initialize(int32_t idx);
/**
\brief De-initialize DMA Interface. stops operation and releases the software resources used by the interface
\param[in] handle damc handle to operate.
\return error code
*/
int32_t csi_dma_uninitialize(dmac_handle_t handle);
/**
\brief Get driver capabilities.
\param[in] idx dmac index.
\return \ref dma_capabilities_t
*/
dma_capabilities_t csi_dma_get_capabilities(int32_t idx);
/**
\brief get one free dma channel
\param[in] handle damc handle to operate.
\param[in] ch channel num. if -1 then allocate a free channal in this dma
\return -1 - no channel can be used, other - channel index
*/
int32_t csi_dma_alloc_channel(dmac_handle_t handle, int32_t ch);
/**
\brief release dma channel and related resources
\param[in] handle damc handle to operate.
\param[in] ch channel num.
\return error code
*/
int32_t csi_dma_release_channel(dmac_handle_t handle, int32_t ch);
/**
\brief
\param[in] handle damc handle to operate.
\param[in] ch channel num. if -1 then allocate a free channal in this dma
\param[in] psrcaddr dma transfer source address
\param[in] pdstaddr dma transfer destination address
\param[in] length dma transfer length (unit: bytes).
\param[in] config dma transfer configure
\param[in] cb_event Pointer to \ref dma_event_cb_t
\return error code if negative, otherwise return the channel num if success.
*/
int32_t csi_dma_config(dmac_handle_t handle, int32_t ch,
void *psrcaddr, void *pdstaddr,
uint32_t length, dma_config_t *config, dma_event_cb_t cb_event);
/**
\brief start generate dma signal.
\param[in] handle damc handle to operate.
\param[in] ch channel num.
\return error code
*/
int32_t csi_dma_start(dmac_handle_t handle, int32_t ch);
/**
\brief Stop generate dma signal.
\param[in] handle damc handle to operate.
\param[in] ch channel num.
\return error code
*/
int32_t csi_dma_stop(dmac_handle_t handle, int32_t ch);
/**
\brief Get DMA status.
\param[in] handle damc handle to operate.
\param[in] ch channel num.
\return DMA status \ref dma_status_e
*/
dma_status_e csi_dma_get_status(dmac_handle_t handle, int32_t ch);
#ifdef __cplusplus
}
#endif
#endif /* _CSI_DMA_H_ */

View file

@ -0,0 +1,159 @@
/*
* Copyright (C) 2017 C-SKY Microsystems Co., Ltd. All rights reserved.
*
* 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_eflash.h
* @brief header file for eflash driver
* @version V1.0
* @date 02. June 2017
******************************************************************************/
#ifndef _CSI_EFLASH_H_
#define _CSI_EFLASH_H_
#ifdef __cplusplus
extern "C" {
#endif
#include <stdint.h>
#include <drv_common.h>
/// definition for eflash handle.
typedef void *eflash_handle_t;
/**
\brief Flash information
*/
typedef struct {
uint32_t start; ///< Chip Start address
uint32_t end; ///< Chip End address (start+size-1)
uint32_t sector_count; ///< Number of sectors
uint32_t sector_size; ///< Uniform sector size in bytes (0=sector_info used)
uint32_t page_size; ///< Optimal programming page size in bytes
uint32_t program_unit; ///< Smallest programmable unit in bytes
uint8_t erased_value; ///< Contents of erased memory (usually 0xFF)
} eflash_info_t;
/**
\brief Flash Status
*/
typedef struct {
uint32_t busy : 1; ///< Flash busy flag
uint32_t error : 1; ///< Read/Program/Erase error flag (cleared on start of next operation)
} eflash_status_t;
/****** EFLASH Event *****/
typedef enum {
EFLASH_EVENT_READY = 0, ///< Flash Ready
EFLASH_EVENT_ERROR , ///< Read/Program/Erase Error
} eflash_event_e;
typedef void (*eflash_event_cb_t)(int32_t idx, eflash_event_e event); ///< Pointer to \ref eflash_event_cb_t : EFLASH Event call back.
/**
\brief Flash Driver Capabilities.
*/
typedef struct {
uint32_t event_ready : 1; ///< Signal Flash Ready event
uint32_t data_width : 2; ///< Data width: 0=8-bit, 1=16-bit, 2=32-bit
uint32_t erase_chip : 1; ///< Supports EraseChip operation
} eflash_capabilities_t;
// Function documentation
/**
\brief Initialize EFLASH Interface. 1. Initializes the resources needed for the EFLASH interface 2.registers event callback function
\param[in] idx dev id
\param[in] cb_event Pointer to \ref eflash_event_cb_t
\return pointer to eflash handle
*/
eflash_handle_t csi_eflash_initialize(int32_t idx, eflash_event_cb_t cb_event);
/**
\brief De-initialize EFLASH Interface. stops operation and releases the software resources used by the interface
\param[in] handle eflash handle to operate.
\return error code
*/
int32_t csi_eflash_uninitialize(eflash_handle_t handle);
/**
\brief Get driver capabilities.
\param[in] idx device id
\return \ref eflash_capabilities_t
*/
eflash_capabilities_t csi_eflash_get_capabilities(int32_t idx);
/**
\brief control eflash power.
\param[in] handle eflash handle to operate.
\param[in] state power state.\ref csi_power_stat_e.
\return error code
*/
int32_t csi_eflash_power_control(eflash_handle_t handle, csi_power_stat_e state);
/**
\brief Read data from Flash.
\param[in] handle eflash handle to operate.
\param[in] addr Data address.
\param[out] data Pointer to a buffer storing the data read from Flash.
\param[in] cnt Number of data items to read.
\return number of data items read or error code
*/
int32_t csi_eflash_read(eflash_handle_t handle, uint32_t addr, void *data, uint32_t cnt);
/**
\brief Program data to Flash.
\param[in] handle eflash handle to operate.
\param[in] addr Data address.
\param[in] data Pointer to a buffer containing the data to be programmed to Flash..
\param[in] cnt Number of data items to program.
\return number of data items programmed or error code
*/
int32_t csi_eflash_program(eflash_handle_t handle, uint32_t addr, const void *data, uint32_t cnt);
/**
\brief Erase Flash Sector.
\param[in] handle eflash handle to operate.
\param[in] addr Sector address
\return error code
*/
int32_t csi_eflash_erase_sector(eflash_handle_t handle, uint32_t addr);
/**
\brief Erase complete Flash.
\param[in] handle eflash handle to operate.
\return error code
*/
int32_t csi_eflash_erase_chip(eflash_handle_t handle);
/**
\brief Get Flash information.
\param[in] handle eflash handle to operate.
\return Pointer to Flash information \ref eflash_info_t
*/
eflash_info_t *csi_eflash_get_info(eflash_handle_t handle);
/**
\brief Get EFLASH status.
\param[in] handle eflash handle to operate.
\return EFLASH status \ref eflash_status_t
*/
eflash_status_t csi_eflash_get_status(eflash_handle_t handle);
#ifdef __cplusplus
}
#endif
#endif /* _CSI_EFLASH_H_ */

View file

@ -0,0 +1,122 @@
/*
* Copyright (C) 2017 C-SKY Microsystems Co., Ltd. All rights reserved.
*
* 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_errno.h
* @brief header file for error num
* @version V1.0
* @date 02. June 2017
******************************************************************************/
/******************************************************************************
* @file
* @details Error code field difination
* Error number is devided into 4 field:
* 0x8******* : 8 : means < 0
* 0x*A****** : A : means type number: bsp(1), driver(2), hal(3), app(4)...
* 0x**AB**** : AB : means module number: timer(1), rtc(2), ....
* 0x****AB** : AB : means API number: module API's definition
* 0x******AB : AB : means sub error number
* 0 ~ 0x80 is common error such as EPERM, refer to errno.h
* 0x80 ~ 0xFF is specific error, can difine in module
*
* For example 0x81020113 means:
* 1. 0x8*******: value < 0, means error happened
* 2. 0x*1******: type number is 1, means bsp error
* 3. 0x**02****: module number is 02, means RTC error
* 4. 0x****01**: module API is 01, means RTC's init
* 5. 0x******13: specific error is 0x13=19=ENODEV, means no such device
*
* For special bsp module example, you can return:
* (BSP_ERRNO_TIMER_BASE | BSP_API_RTC_INIT | EPERM) for rtc init error
* (BSP_ERRNO_TIMER_BASE | BSP_API_RTC_SETTIME | ENXIO) for rtc settime error
*
* Here list the common sub error number (0x******AB) below(0~127 defined in errno.h as standard err code):
* Code Hex Deci Meaning
* -------------------------------------------------------
* EPERM 0x01 1 Operation not permitted
* EIO 0x05 5 I/O error
* ENXIO 0x06 6 No such device or address
* ENOMEM 0x0C 12 Out of memory
* EACCES 0x0D 13 Permission denied
* EINVAL 0x16 22 Invalid argument
* ...
* SPEC_ERR_BASE 0x80 128 module special error number base
* ...
* ERRNO_MAX 0xFF -- Max sub error number
******************************************************************************/
#ifndef _DRV_ERRNO_H_
#define _DRV_ERRNO_H_
#include <errno.h>
#define ERRNO_DRV_START 0X80
/* drvier General return codes */
typedef enum {
DRV_ERROR = ERRNO_DRV_START, ///< Unspecified error
DRV_ERROR_BUSY, ///< Driver is busy
DRV_ERROR_TIMEOUT, ///< Timeout occurred
DRV_ERROR_UNSUPPORTED, ///< Operation not supported
DRV_ERROR_PARAMETER, ///< Parameter error
DRV_ERROR_SPECIFIC ///< Start of driver specific errors
} drv_err_e;
/** Get error type */
#define GET_ERROR_TYPE(errno) \
(error & 0xFF000000 >> 24)
/** Get error module */
#define GET_ERROR_MODULE(error) \
(error & 0x00FF0000 >> 16)
/** Get error API */
#define GET_ERROR_API(error) \
(error & 0x0000FF00 >> 8)
/** Get errno */
#define GET_ERROR_NUM(error) \
(error & 0x000000FF)
#ifndef CSI_DRV_ERRNO_BASE
/** means bsp errors */
#define CSI_DRV_ERRNO_BASE 0x81000000
#endif
/** driver module id definition*/
#define CSI_DRV_ERRNO_GPIO_BASE 0x81010000
#define CSI_DRV_ERRNO_USART_BASE 0x81020000
#define CSI_DRV_ERRNO_SPI_BASE 0x81030000
#define CSI_DRV_ERRNO_I2C_BASE 0x81040000
#define CSI_DRV_ERRNO_PWM_BASE 0x81060000
#define CSI_DRV_ERRNO_RTC_BASE 0x81070000
#define CSI_DRV_ERRNO_TIMER_BASE 0x81080000
#define CSI_DRV_ERRNO_WDT_BASE 0x81090000
#define CSI_DRV_ERRNO_AES_BASE 0x810A0000
#define CSI_DRV_ERRNO_CRC_BASE 0x810B0000
#define CSI_DRV_ERRNO_RSA_BASE 0x810C0000
#define CSI_DRV_ERRNO_SHA_BASE 0x810D0000
#define CSI_DRV_ERRNO_TRNG_BASE 0x810E0000
#define CSI_DRV_ERRNO_EFLASH_BASE 0x810F0000
#define CSI_DRV_ERRNO_DMA_BASE 0x81100000
#define CSI_DRV_ERRNO_NORFLASH_BASE 0x81110000
#define CSI_DRV_ERRNO_INTC_BASE 0x81120000
#define CSI_DRV_ERRNO_SPU_BASE 0x81130000
#define CSI_DRV_ERRNO_ADC_BASE 0x81140000
#define CSI_DRV_ERRNO_PMU_BASE 0x81150000
#define CSI_DRV_ERRNO_BMU_BASE 0x81160000
#define CSI_DRV_ERRNO_ETB_BASE 0x81170000
#endif /* CSI_DRV_ERRNO_H */

View file

@ -0,0 +1,132 @@
/*
* Copyright (C) 2017 C-SKY Microsystems Co., Ltd. All rights reserved.
*
* 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_etb.h
* @brief header file for event trigger driver
* @version V1.0
* @date 27. octorber 2017
******************************************************************************/
#ifndef _CSI_ETB_H_
#define _CSI_ETB_H_
#ifdef __cplusplus
extern "C" {
#endif
#include <stdint.h>
#include <soc.h>
typedef enum {
ETB_SOURCE = 0,
ETB_DEST = 1
} etb_direct_e;
typedef enum {
ETB_HARDWARE = 0, ///< etb channel inout is hardware trigger.
ETB_SOFTWWARE ///< etb channel inout is software trigger.
} etb_source_type_e;
typedef enum {
ETB_ONE_TRIGGER_ONE = 0,
ETB_ONE_TRIGGER_MORE = 1,
ETB_MORE_TRIGGER_ONE = 2
} etb_channel_func_e;
/// definition for etb handle.
typedef void *etb_handle_t;
typedef struct {
uint32_t busy : 1;
} etb_status_t;
typedef enum {
ETB_EVENT_CHANNEL_BUSY = 0, ///<
ETB_EVENT_MODE_FAULT ///<
} etb_event_e;
/**
\brief ETB Driver Capabilities.
*/
typedef struct {
uint32_t sync_trigger : 1;
uint32_t async_trigger : 1;
uint32_t etb_31_channel : 1;
uint32_t one_trigger_one : 1;
uint32_t one_trigger_more : 1;
uint32_t more_trigger_one : 1;
} etb_capabilities_t;
typedef void (*etb_event_cb_t)(int32_t idx, etb_event_e event); ///< Pointer to \ref etb_event_cb_t : etb Event call back.
/**
\brief Initialize etb Interface. 1. Initializes the resources needed for the etb interface 2.registers event callback function.
\param[in] idx etb index.
\param[in] cb_event event call back function \ref etb_event_cb_t
\return return etb handle if success
*/
etb_handle_t csi_etb_initialize(int32_t idx, etb_event_cb_t cb_event);
/**
\brief De-initialize etb Interface. stops operation and releases the software resources used by the interface
\param[in] handle etb handle to operate.
\return error code
*/
int32_t csi_etb_uninitialize(etb_handle_t handle);
/**
\brief Get driver capabilities.
\param[in] idx etb index.
\return \ref etb_capabilities_t
*/
etb_capabilities_t csi_etb_get_capabilities(int32_t idx);
/**
\brief config etb channel.
\param[in] handle etb handle to operate.
\param[in] source_lo a specific number represent a location in an source trigger location map to trigger other ip(s).
\param[in] dest_lo a specific number represent an location in an dest trigger map to wait signal(s) from source ip(s) or location(s).
\param[in] source_type \ref etb_source_type_e the input source is hardware trigger or software trigger.
\param[in] mode \ref etb_channel_func_e channel function.
\return channel nubmber or error code (negative).
*/
int32_t csi_etb_channel_config(etb_handle_t handle, uint32_t source_ip, uint32_t dest_ip, etb_source_type_e source_type, etb_channel_func_e mode);
/**
\brief start etb.
\param[in] handle etb handle to operate.
\param[in] channel etb channel number to operate.
\return error code
*/
int32_t csi_etb_start(etb_handle_t handle, int32_t channel);
/**
\brief stop etb.
\param[in] handle etb handle to operate.
\param[in] channel etb channel number to operate.
\return error code
*/
int32_t csi_etb_stop(etb_handle_t handle, int32_t channel);
/**
\brief Get ETB status.
\param[in] handle etb handle to operate.
\return ETB status \ref etb_status_t
*/
etb_status_t csi_etb_get_status(etb_handle_t handle);
#endif /* _CSI_ETB_H_ */

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