From commits-return-15582-archive-asf-public=cust-asf.ponee.io@mynewt.apache.org Thu Jan 18 18:54:44 2018 Return-Path: X-Original-To: archive-asf-public@eu.ponee.io Delivered-To: archive-asf-public@eu.ponee.io Received: from cust-asf.ponee.io (cust-asf.ponee.io [163.172.22.183]) by mx-eu-01.ponee.io (Postfix) with ESMTP id 5071A180654 for ; Thu, 18 Jan 2018 18:54:44 +0100 (CET) Received: by cust-asf.ponee.io (Postfix) id 3F819160C48; Thu, 18 Jan 2018 17:54:44 +0000 (UTC) Delivered-To: archive-asf-public@cust-asf.ponee.io Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by cust-asf.ponee.io (Postfix) with SMTP id B9AD6160C26 for ; Thu, 18 Jan 2018 18:54:34 +0100 (CET) Received: (qmail 42635 invoked by uid 500); 18 Jan 2018 17:54:33 -0000 Mailing-List: contact commits-help@mynewt.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@mynewt.apache.org Delivered-To: mailing list commits@mynewt.apache.org Received: (qmail 42626 invoked by uid 99); 18 Jan 2018 17:54:33 -0000 Received: from ec2-52-202-80-70.compute-1.amazonaws.com (HELO gitbox.apache.org) (52.202.80.70) by apache.org (qpsmtpd/0.29) with ESMTP; Thu, 18 Jan 2018 17:54:33 +0000 From: GitBox To: commits@mynewt.apache.org Subject: [GitHub] wes3 closed pull request #711: Initial ARCv2 port of mynewt Message-ID: <151629807252.27102.13830932760022301618.gitbox@gitbox.apache.org> wes3 closed pull request #711: Initial ARCv2 port of mynewt URL: https://github.com/apache/mynewt-core/pull/711 This is a PR merged from a forked repository. As GitHub hides the original diff on merge, it is displayed below for the sake of provenance: As this is a foreign pull request (from a fork), the diff is supplied below (as it won't show otherwise due to GitHub magic): diff --git a/LICENSE b/LICENSE index 6ead48c0d..bc28d9b11 100644 --- a/LICENSE +++ b/LICENSE @@ -448,3 +448,7 @@ This product bundles RobotSlab by Christian Robertson, which is available under the Apache License v2.0. Bundled files are: * docs/themes/mynewt/static/fonts/RobotoSlab-Bold.ttf * docs/themes/mynewt/static/fonts/RobotoSlab-Regular.ttf + +This product bundles part of embARC BSP SDK by Synopsys, which is available +under the "3-clause BSD" license. Bundled files are: + * hw/mcu/arc/src/ext/sdk diff --git a/compiler/arc/compiler.yml b/compiler/arc/compiler.yml new file mode 100644 index 000000000..9123f9101 --- /dev/null +++ b/compiler/arc/compiler.yml @@ -0,0 +1,36 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you 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. +# + +compiler.path.cc: arc-elf32-gcc +compiler.path.cpp: arc-elf32-g++ +compiler.path.archive: arc-elf32-ar +compiler.path.as: arc-elf32-gcc +compiler.path.objdump: arc-elf32-objdump +compiler.path.objsize: arc-elf32-size +compiler.path.objcopy: arc-elf32-objcopy + +compiler.flags.default: -mno-sdata -Wall -Werror -fno-exceptions -fomit-frame-pointer -ffunction-sections -fdata-sections +compiler.flags.optimized: [compiler.flags.default, -Os -ggdb] +compiler.flags.debug: [compiler.flags.default, -Og -ggdb] + +compiler.as.flags: [-x, assembler-with-cpp] + +compiler.ld.flags: -static -specs=nosys.specs -lgcc -Wl,--gc-sections -nostartfiles +compiler.ld.resolve_circular_deps: true +compiler.ld.mapfile: true diff --git a/compiler/arc/pkg.yml b/compiler/arc/pkg.yml new file mode 100644 index 000000000..13d99a8ac --- /dev/null +++ b/compiler/arc/pkg.yml @@ -0,0 +1,27 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you 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. +# + +pkg.name: compiler/arc +pkg.type: compiler +pkg.description: Compiler definition for ARC gcc cross compiler. +pkg.author: "Apache Mynewt " +pkg.homepage: "http://mynewt.apache.org/" +pkg.keywords: + - arc + - compiler diff --git a/hw/bsp/embarc_emsk/arc_core.ld b/hw/bsp/embarc_emsk/arc_core.ld new file mode 100644 index 000000000..f1881ce3f --- /dev/null +++ b/hw/bsp/embarc_emsk/arc_core.ld @@ -0,0 +1,128 @@ +/* ------------------------------------------ + * Copyright (c) 2017, Synopsys, Inc. All rights reserved. + + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + + * 1) Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + + * 2) 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. + + * 3) Neither the name of the Synopsys, Inc., nor the names of its contributors may + * be used to endorse or promote products derived from this software without + * specific prior written permission. + + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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. +--------------------------------------------- */ +MEMORY +{ + ICCM : ORIGIN = 0x00000000, LENGTH = 0x40000 + DCCM : ORIGIN = 0x80000000, LENGTH = 0x40000 + DMP : ORIGIN = 0xf0000000, LENGTH = 0x10000000 +} +ENTRY(_start) +SECTIONS +{ + .vector : ALIGN(1024) + { + _f_vector = .; + *(.vector) + _e_vector = .; + } > ICCM + + .init : + { + _f_init = .; + KEEP (*(.init_vector)) + KEEP (*(.init_bootstrap)) + _e_init = .; + } > ICCM + + .text : ALIGN(4) + { + _f_text = .; + *(.text .text.* .gnu.linkonce.t.*) + _e_text = .; + } > ICCM + + .rodata : ALIGN(4) + { + _f_rodata = .; + . = ALIGN(4); + __CTOR_LIST__ = .; + LONG((__CTOR_END__ - __CTOR_LIST__) / 4 - 2) + KEEP(*(SORT_BY_NAME(".ctors*"))) + LONG(0) + __CTOR_END__ = .; + . = ALIGN(4); + __init_array_start = .; + KEEP(*(SORT_BY_NAME(".init_array*"))) + __init_array_end = .; + . = ALIGN(4); + __DTOR_LIST__ = .; + LONG((__DTOR_END__ - __DTOR_LIST__) / 4 - 2) + KEEP(*(SORT_BY_NAME(".dtors*"))) + LONG(0) + __DTOR_END__ = .; + *(.rodata .rodata.* .gnu.linkonce.r.*) + _e_rodata = .; + } > ICCM + + .data : ALIGN(4) + { + _ram_start = .; + _f_data = .; + *(.data .data.* .gnu.linkonce.d.*) + _f_sdata = .; + __SDATA_BEGIN__ = .; + *(.sdata .sdata.* .gnu.linkonce.s.*) + _e_sdata = .; + _e_data = .; + } > DCCM AT > ICCM + + .bss (NOLOAD) : ALIGN(8) + { + PROVIDE (__sbss_start = .); + PROVIDE (___sbss_start = .); + _f_bss = .; + _f_sbss = .; + *(.dynsbss) + *(.sbss .sbss.* .gnu.linkonce.sb.*) + *(.scommon) + _e_sbss = .; + PROVIDE (__sbss_end = .); + PROVIDE (___sbss_end = .); + *(.dynbss) + *(.bss .bss.* .gnu.linkonce.b.*) + *(COMMON) + _e_bss = .; + } > DCCM + + /* Allocate remaining RAM (RAM between _e_bss and __StackLimit to heap */ + . = ALIGN(4); + __HeapBase = .; + + __StackTop = ORIGIN(DCCM) + LENGTH(DCCM); + __StackLimit = __StackTop - 2048; + _e_stack = __StackTop; + + /* Top of heap is the bottom of the stack */ + __HeapLimit = __StackLimit; + + _load_addr_text = LOADADDR(.text); + _load_addr_rodata = LOADADDR(.rodata); + _load_addr_data = LOADADDR(.data); + _ram_start = _load_addr_data; +} diff --git a/hw/bsp/embarc_emsk/bsp.yml b/hw/bsp/embarc_emsk/bsp.yml new file mode 100644 index 000000000..9852c7284 --- /dev/null +++ b/hw/bsp/embarc_emsk/bsp.yml @@ -0,0 +1,62 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you 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. +# + +bsp.arch: arc +bsp.compiler: compiler/arc +bsp.linkerscript: + - "hw/bsp/embarc_emsk/arc_core.ld" +bsp.linkerscript.BOOT_LOADER.OVERWRITE: + - "hw/bsp/embarc_emsk/arc_core.ld" +bsp.part2linkerscript: "hw/bsp/embarc_emsk/arc_core.ld" +bsp.downloadscript: "hw/bsp/embarc_emsk/embarc_emsk_download.sh" +bsp.debugscript: "hw/bsp/embarc_emsk/embarc_emsk_debug.sh" +bsp.downloadscript.WINDOWS.OVERWRITE: "hw/bsp/embarc_emsk/embarc_emsk_download.cmd" +bsp.debugscript.WINDOWS.OVERWRITE: "hw/bsp/embarc_emsk/embarc_emsk_debug.cmd" + +bsp.flash_map: + areas: + # System areas. + FLASH_AREA_BOOTLOADER: + device: 0 + offset: 0x10000000 + size: 16kB + FLASH_AREA_IMAGE_0: + device: 0 + offset: 0x10008000 + size: 232kB + FLASH_AREA_IMAGE_1: + device: 0 + offset: 0x10042000 + size: 232kB + FLASH_AREA_IMAGE_SCRATCH: + device: 0 + offset: 0x1007c000 + size: 4kB + + # User areas. + FLASH_AREA_REBOOT_LOG: + user_id: 0 + device: 0 + offset: 0x10004000 + size: 16kB + FLASH_AREA_NFFS: + user_id: 1 + device: 0 + offset: 0x1007d000 + size: 12kB diff --git a/hw/bsp/embarc_emsk/include/bsp/arc_core_config.h b/hw/bsp/embarc_emsk/include/bsp/arc_core_config.h new file mode 100644 index 000000000..6c06ce94c --- /dev/null +++ b/hw/bsp/embarc_emsk/include/bsp/arc_core_config.h @@ -0,0 +1,179 @@ +/* ------------------------------------------ + * Copyright (c) 2017, Synopsys, Inc. All rights reserved. + + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + + * 1) Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + + * 2) 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. + + * 3) Neither the name of the Synopsys, Inc., nor the names of its contributors may + * be used to endorse or promote products derived from this software without + * specific prior written permission. + + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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. +--------------------------------------------- */ +#ifndef __core_config_h + #define __core_config_h 1 + #define core_config_cir_identity 0x00000142 + #define core_config_cir_identity_chipid 0 + #define core_config_cir_identity_arcnum 1 + #define core_config_cir_identity_arcver 66 + #define core_config_cir_identity_family 4 + #define core_config_cir_identity_corever 2 + #define core_config_cir_aux_dccm 0x80000000 + #define core_config_bcr_bcr_ver 0x00000002 + #define core_config_bcr_bcr_ver_version 2 + #define core_config_bcr_vecbase_ac_build 0x00000010 + #define core_config_bcr_rf_build 0x0000c802 + #define core_config_bcr_rf_build_version 2 + #define core_config_bcr_rf_build_p 0 + #define core_config_bcr_rf_build_e 0 + #define core_config_bcr_rf_build_r 0 + #define core_config_bcr_rf_build_b 1 + #define core_config_bcr_rf_build_d 3 + #define core_config_bcr_dccm_build 0x00000a04 + #define core_config_bcr_dccm_build_w 0 + #define core_config_bcr_dccm_build_cycles 0 + #define core_config_bcr_dccm_build_interleave 0 + #define core_config_bcr_dccm_build_size1 0 + #define core_config_bcr_dccm_build_size0 10 + #define core_config_bcr_dccm_build_version 4 + #define core_config_bcr_timer_build 0x00010304 + #define core_config_bcr_timer_build_sp1 0 + #define core_config_bcr_timer_build_sp0 0 + #define core_config_bcr_timer_build_p1 0 + #define core_config_bcr_timer_build_p0 1 + #define core_config_bcr_timer_build_st1 0 + #define core_config_bcr_timer_build_st0 0 + #define core_config_bcr_timer_build_rtc 0 + #define core_config_bcr_timer_build_rtsc_ver 1 + #define core_config_bcr_timer_build_rtsc 0 + #define core_config_bcr_timer_build_t0 1 + #define core_config_bcr_timer_build_t1 1 + #define core_config_bcr_timer_build_version 4 + #define core_config_bcr_iccm_build 0x00000a04 + #define core_config_bcr_iccm_build_iccm1_size1 0 + #define core_config_bcr_iccm_build_iccm0_size1 0 + #define core_config_bcr_iccm_build_iccm1_size0 0 + #define core_config_bcr_iccm_build_iccm0_size0 10 + #define core_config_bcr_iccm_build_version 4 + #define core_config_bcr_dsp_build 0x00001121 + #define core_config_bcr_dsp_build_wide 0 + #define core_config_bcr_dsp_build_itu_pa 0 + #define core_config_bcr_dsp_build_acc_shift 2 + #define core_config_bcr_dsp_build_comp 0 + #define core_config_bcr_dsp_build_divsqrt 1 + #define core_config_bcr_dsp_build_version 33 + #define core_config_bcr_multiply_build 0x00022a06 + #define core_config_bcr_multiply_build_version16x16 2 + #define core_config_bcr_multiply_build_dsp 2 + #define core_config_bcr_multiply_build_cyc 2 + #define core_config_bcr_multiply_build_type 2 + #define core_config_bcr_multiply_build_version32x32 6 + #define core_config_bcr_swap_build 0x00000003 + #define core_config_bcr_swap_build_version 3 + #define core_config_bcr_norm_build 0x00000003 + #define core_config_bcr_norm_build_version 3 + #define core_config_bcr_minmax_build 0x00000002 + #define core_config_bcr_minmax_build_version 2 + #define core_config_bcr_barrel_build 0x00000303 + #define core_config_bcr_barrel_build_version 3 + #define core_config_bcr_barrel_build_shift_option 3 + #define core_config_bcr_isa_config 0x12447402 + #define core_config_bcr_isa_config_res1 0 + #define core_config_bcr_isa_config_d 1 + #define core_config_bcr_isa_config_res2 0 + #define core_config_bcr_isa_config_f 0 + #define core_config_bcr_isa_config_c 2 + #define core_config_bcr_isa_config_l 0 + #define core_config_bcr_isa_config_n 1 + #define core_config_bcr_isa_config_a 0 + #define core_config_bcr_isa_config_b 0 + #define core_config_bcr_isa_config_addr_size 4 + #define core_config_bcr_isa_config_lpc_size 7 + #define core_config_bcr_isa_config_pc_size 4 + #define core_config_bcr_isa_config_version 2 + #define core_config_bcr_stack_region_build 0x00000002 + #define core_config_bcr_cprot_build 0x00000001 + #define core_config_bcr_core_config 0x00000101 + #define core_config_bcr_core_config_turbo_boost 1 + #define core_config_bcr_core_config_version 1 + #define core_config_bcr_irq_build 0x030b1401 + #define core_config_bcr_irq_build_raz 0 + #define core_config_bcr_irq_build_f 0 + #define core_config_bcr_irq_build_p 3 + #define core_config_bcr_irq_build_exts 11 + #define core_config_bcr_irq_build_irqs 20 + #define core_config_bcr_irq_build_version 1 + #define core_config_cir_aux_iccm 0x00000000 + #define core_config_cir_dmp_peripheral 0xf0000000 + #define core_config_family 4 + #define core_config_core_version 2 + #define core_config_family_name "arcv2em" + #define core_config_rgf_num_banks 2 + #define core_config_rgf_banked_regs 32 + #define core_config_rgf_num_wr_ports 1 + #define core_config_endian "little" + #define core_config_endian_little 1 + #define core_config_endian_big 0 + #define core_config_lpc_size 32 + #define core_config_pc_size 32 + #define core_config_addr_size 32 + #define core_config_unaligned 1 + #define core_config_code_density 1 + #define core_config_div_rem "radix2" + #define core_config_div_rem_radix2 1 + #define core_config_turbo_boost 1 + #define core_config_swap 1 + #define core_config_bitscan 1 + #define core_config_mpy_option "mpyd" + #define core_config_mpy_option_num 8 + #define core_config_shift_assist 1 + #define core_config_barrel_shifter 1 + #define core_config_dsp 1 + #define core_config_dsp2 1 + #define core_config_dsp_divsqrt "radix2" + #define core_config_dsp_divsqrt_radix2 1 + #define core_config_dsp_accshift "full" + #define core_config_dsp_accshift_full 1 + #define core_config_timer0 1 + #define core_config_timer0_level 1 + #define core_config_timer0_vector 16 + #define core_config_timer1 1 + #define core_config_timer1_level 0 + #define core_config_timer1_vector 17 + #define core_config_stack_check 1 + #define core_config_code_protection 1 + #define core_config_interrupts_present 1 + #define core_config_interrupts_number 20 + #define core_config_interrupts_priorities 4 + #define core_config_interrupts_externals 11 + #define core_config_interrupts 20 + #define core_config_interrupt_priorities 4 + #define core_config_ext_interrupts 11 + #define core_config_interrupts_base 0x0 + #define core_config_dccm_present 1 + #define core_config_dccm_size 0x40000 + #define core_config_dccm_base 0x80000000 + #define core_config_iccm_present 1 + #define core_config_iccm0_present 1 + #define core_config_iccm_size 0x40000 + #define core_config_iccm0_size 0x40000 + #define core_config_iccm_base 0x00000000 + #define core_config_iccm0_base 0x00000000 + #define core_config_clock_speed 40 +#endif /* __core_config_h */ diff --git a/hw/bsp/embarc_emsk/include/bsp/bsp.h b/hw/bsp/embarc_emsk/include/bsp/bsp.h new file mode 100644 index 000000000..ec32214a6 --- /dev/null +++ b/hw/bsp/embarc_emsk/include/bsp/bsp.h @@ -0,0 +1,39 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. + */ + +#ifndef H_BSP_H +#define H_BSP_H + +#include + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* XXX: a hack for now. Just allocate 262K of ram. Only used for coredump */ +extern uint32_t _ram_start; +#define RAM_SIZE 0x40000 + +#ifdef __cplusplus +} +#endif + +#endif /* H_BSP_H */ diff --git a/hw/bsp/embarc_emsk/include/bsp/embARC_BSP_config.h b/hw/bsp/embarc_emsk/include/bsp/embARC_BSP_config.h new file mode 100644 index 000000000..4598b003d --- /dev/null +++ b/hw/bsp/embarc_emsk/include/bsp/embARC_BSP_config.h @@ -0,0 +1,66 @@ +/* ------------------------------------------ + * Copyright (c) 2016, Synopsys, Inc. All rights reserved. + + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + + * 1) Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + + * 2) 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. + + * 3) Neither the name of the Synopsys, Inc., nor the names of its contributors may + * be used to endorse or promote products derived from this software without + * specific prior written permission. + + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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. + * + * \version 2016.05 + * \date 2014-12-25 + * \author Wayne Ren(Wei.Ren@synopsys.com) +--------------------------------------------- */ + +#ifndef _EMBARC_BSP_CONFIG_H_ +#define _EMBARC_BSP_CONFIG_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#define BOARD_EMSK +/**************************************************************************** + * BSP Definitions + ****************************************************************************/ +/** + * Toolchain Definition for MetaWare or GNU + */ +//#define __MW__ +#define __GNU__ + +/** + * Must be set. + * If changed, modify .lcf file for + * .stack ALIGN(4) SIZE(524288): {} + * .heap? ALIGN(4) SIZE(524288): {} + */ +#define _STACKSIZE 8192 +#define _HEAPSZ 8192 + + + +#ifdef __cplusplus +} +#endif + +#endif /* _EMBARC_CONFIG_BSP_H_ */ diff --git a/hw/bsp/embarc_emsk/pkg.yml b/hw/bsp/embarc_emsk/pkg.yml new file mode 100644 index 000000000..1529fb520 --- /dev/null +++ b/hw/bsp/embarc_emsk/pkg.yml @@ -0,0 +1,33 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you 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. +# + +pkg.name: hw/bsp/embarc_emsk +pkg.type: bsp +pkg.description: BSP definition for the embarc emsk Development Kit. +pkg.author: "Apache Mynewt " +pkg.homepage: "http://mynewt.apache.org/" +pkg.keywords: + - arc + - embarc_emsk + +pkg.deps: + - hw/mcu/arc/snps + - libc/baselibc + +pkg.cflags: -mcpu=em4_dmips -mlittle-endian -mcode-density -mdiv-rem -mswap -mbarrel-shifter diff --git a/hw/bsp/embarc_emsk/src/board.c b/hw/bsp/embarc_emsk/src/board.c new file mode 100644 index 000000000..634c7e40f --- /dev/null +++ b/hw/bsp/embarc_emsk/src/board.c @@ -0,0 +1,50 @@ +/* ------------------------------------------ + * Copyright (c) 2017, Synopsys, Inc. All rights reserved. + + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + + * 1) Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + + * 2) 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. + + * 3) Neither the name of the Synopsys, Inc., nor the names of its contributors may + * be used to endorse or promote products derived from this software without + * specific prior written permission. + + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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. + * + * \version 2017.03 + * \date 2016-01-20 + * \author Wayne Ren(Wei.Ren@synopsys.com) +--------------------------------------------- */ +#include "inc/arc/arc_builtin.h" +#include "board/board.h" +#include "string.h" + +extern uint32_t __HeapBase; +extern uint32_t __HeapLimit; + +extern void _start(void); +extern void _sbrkInit(char *base, char *limit); + +void board_main(void) +{ +/* board level hardware init */ + board_init(); + cpu_unlock(); /* unlock cpu to let interrupt work */ + _sbrkInit((char *)&__HeapBase, (char *)&__HeapLimit); + _start(); +} diff --git a/hw/bsp/embarc_emsk/src/hal_bsp.c b/hw/bsp/embarc_emsk/src/hal_bsp.c new file mode 100644 index 000000000..80e59175b --- /dev/null +++ b/hw/bsp/embarc_emsk/src/hal_bsp.c @@ -0,0 +1,109 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 +#include +#include +#include "os/os_cputime.h" +#include "syscfg/syscfg.h" +#include "sysflash/sysflash.h" +#include "flash_map/flash_map.h" +#include "hal/hal_bsp.h" +#include "hal/hal_system.h" +#include "hal/hal_flash.h" +#include "hal/hal_spi.h" +#include "hal/hal_watchdog.h" +#include "hal/hal_i2c.h" +#if MYNEWT_VAL(UART_0) || MYNEWT_VAL(UART_1) +#include "uart/uart.h" +#endif +#if MYNEWT_VAL(UART_0) +#include "uart_hal/uart_hal.h" +#endif +#if MYNEWT_VAL(UART_1) +#include "uart_bitbang/uart_bitbang.h" +#endif +#include "os/os_dev.h" +#include "bsp/bsp.h" + +/* + * What memory to include in coredump. + */ +static const struct hal_bsp_mem_dump dump_cfg[] = { + [0] = { + .hbmd_start = &_ram_start, + .hbmd_size = RAM_SIZE + } +}; + +const struct hal_flash * +hal_bsp_flash_dev(uint8_t id) +{ + return NULL; +} + +const struct hal_bsp_mem_dump * +hal_bsp_core_dump(int *area_cnt) +{ + *area_cnt = sizeof(dump_cfg) / sizeof(dump_cfg[0]); + return dump_cfg; +} + +int +hal_bsp_power_state(int state) +{ + return (0); +} + +/** + * Returns the configured priority for the given interrupt. If no priority + * configured, return the priority passed in + * + * @param irq_num + * @param pri + * + * @return uint32_t + */ +uint32_t +hal_bsp_get_nvic_priority(int irq_num, uint32_t pri) +{ + return pri; +} + +void +hal_bsp_init(void) +{ + int rc; + + (void)rc; + + /* Make sure system clocks have started */ + hal_system_clock_start(); + +#if MYNEWT_VAL(TIMER_0) + rc = hal_timer_init(0, NULL); + assert(rc == 0); +#endif + +#if (MYNEWT_VAL(OS_CPUTIME_TIMER_NUM) >= 0) + rc = os_cputime_init(MYNEWT_VAL(OS_CPUTIME_FREQ)); + assert(rc == 0); +#endif + +} diff --git a/hw/bsp/embarc_emsk/src/sbrk.c b/hw/bsp/embarc_emsk/src/sbrk.c new file mode 100644 index 000000000..779f9782f --- /dev/null +++ b/hw/bsp/embarc_emsk/src/sbrk.c @@ -0,0 +1,60 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 + +/* put these in the data section so they are not cleared by _start */ +static char *sbrkBase __attribute__ ((section (".data"))); +static char *sbrkLimit __attribute__ ((section (".data"))); +static char *brk __attribute__ ((section (".data"))); + +void +_sbrkInit(char *base, char *limit) +{ + sbrkBase = base; + sbrkLimit = limit; + brk = base; +} + +void * +_sbrk(int incr) +{ + void *prev_brk; + + if (incr < 0) { + /* Returning memory to the heap. */ + incr = -incr; + if (brk - incr < sbrkBase) { + prev_brk = (void *)-1; + } else { + prev_brk = brk; + brk -= incr; + } + } else { + /* Allocating memory from the heap. */ + if (sbrkLimit - brk >= incr) { + prev_brk = brk; + brk += incr; + } else { + prev_brk = (void *)-1; + } + } + + return prev_brk; +} diff --git a/hw/bsp/embarc_emsk/syscfg.yml b/hw/bsp/embarc_emsk/syscfg.yml new file mode 100644 index 000000000..230404752 --- /dev/null +++ b/hw/bsp/embarc_emsk/syscfg.yml @@ -0,0 +1,42 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you 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. +# + +# Package: hw/bsp/embarc_emsk + +syscfg.defs: + UART_0: + description: 'Whether to enable UART0' + value: 0 + UART_0_PIN_TX: + description: 'TX pin for UART0' + value: -1 + UART_0_PIN_RX: + description: 'RX pin for UART0' + value: -1 + UART_0_PIN_RTS: + description: 'RTS pin for UART0' + value: -1 + UART_0_PIN_CTS: + description: 'CTS pin for UART0' + value: -1 + +syscfg.vals: + CONFIG_FCB_FLASH_AREA: FLASH_AREA_NFFS + REBOOT_LOG_FLASH_AREA: FLASH_AREA_REBOOT_LOG + NFFS_FLASH_AREA: FLASH_AREA_NFFS + COREDUMP_FLASH_AREA: FLASH_AREA_IMAGE_1 diff --git a/hw/mcu/arc/pkg.yml b/hw/mcu/arc/pkg.yml new file mode 100644 index 000000000..db5c87e6a --- /dev/null +++ b/hw/mcu/arc/pkg.yml @@ -0,0 +1,39 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you 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. +# + +pkg.name: hw/mcu/arc +pkg.description: Common MCU definitions for ARC chips. +pkg.author: "Apache Mynewt " +pkg.homepage: "http://mynewt.apache.org/" +pkg.keywords: + - arc + +pkg.type: sdk + +pkg.ign_dirs: + - "src/ext/sdk/example/" + - "src/ext/sdk/doc/" + +pkg.cflags: -Wno-unused-but-set-variable -Wno-unused-function + +pkg.src_dirs: + - "src/ext/sdk/" + +pkg.deps: + - hw/hal diff --git a/hw/mcu/arc/snps/include/mcu/mcu_arc.h b/hw/mcu/arc/snps/include/mcu/mcu_arc.h new file mode 100644 index 000000000..97e8a5562 --- /dev/null +++ b/hw/mcu/arc/snps/include/mcu/mcu_arc.h @@ -0,0 +1,35 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. + */ + +#ifndef __MCU_ARC_H__ +#define __MCU_ARC_H__ + +#include "syscfg/syscfg.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define OS_TICKS_PER_SEC (100) + +#ifdef __cplusplus +} +#endif + +#endif /* __MCU_ARC_H__ */ diff --git a/hw/mcu/arc/snps/pkg.yml b/hw/mcu/arc/snps/pkg.yml new file mode 100644 index 000000000..2d49676db --- /dev/null +++ b/hw/mcu/arc/snps/pkg.yml @@ -0,0 +1,29 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you 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. +# + +pkg.name: hw/mcu/arc/snps +pkg.description: MCU definition for synopsis ARC. +pkg.author: "Apache Mynewt " +pkg.homepage: "http://mynewt.apache.org/" +pkg.keywords: + - arc + +pkg.deps: + - hw/hal + - hw/mcu/arc diff --git a/hw/mcu/arc/snps/src/arch/arc/arc_startup.S b/hw/mcu/arc/snps/src/arch/arc/arc_startup.S new file mode 100644 index 000000000..fbcf0d884 --- /dev/null +++ b/hw/mcu/arc/snps/src/arch/arc/arc_startup.S @@ -0,0 +1,264 @@ +/* ------------------------------------------ + * Copyright (c) 2016, Synopsys, Inc. All rights reserved. + + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + + * 1) Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + + * 2) 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. + + * 3) Neither the name of the Synopsys, Inc., nor the names of its contributors may + * be used to endorse or promote products derived from this software without + * specific prior written permission. + + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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. + * + * \version 2016.05 + * \date 2014-07-15 + * \author Wayne Ren(Wei.Ren@synopsys.com) +--------------------------------------------- */ + +/** + * \file + * \ingroup ARC_HAL_STARTUP + * \brief assembly part of startup process + */ + +/** + * \addtogroup ARC_HAL_STARTUP + * @{ + */ +/** @cond STARTUP_ASM */ + +#define __ASSEMBLY__ +#include "embARC_BSP_config.h" +#include "inc/arc/arc.h" + + .file "arc_startup.S" + +.weak _f_sdata /* start of small data, defined in link script */ +.weak init_hardware_hook /* app hardware init hook */ +.weak init_software_hook /* app software init hook */ + +.extern board_main +.extern exc_entry_table + +/* initial vector table */ + .section .init_vector, "a" + .long _arc_reset + .section .init_bootstrap, "ax" + .global _arc_reset + .align 4 +_arc_reset: +_arc_reset_stage1: + kflag STATUS32_RESET_VALUE + +/* STAGE 1 */ + +/* necessary hardware should be done first to speed up initialization + 1. system clk + 2. mem controller must be initialized before any access to external + mem. + 3. others +*/ +_arc_cache_init_start: + lr r0, [AUX_BCR_D_CACHE] + cmp r0, 2 + /* invalidate dcache */ + jle _arc_icache_init + mov r0, 1 + sr r0, [AUX_DC_IVDC] + sr r0, [AUX_DC_CTRL] +_arc_icache_init: + lr r0, [AUX_BCR_I_CACHE] + cmp r0, 2 + jle _arc_cache_init_end + /* invalidate icache */ + mov r0, 1 + sr r0, [AUX_IC_IVIC] + nop_s + nop_s + nop_s + sr r0, [AUX_IC_CTRL] + +_arc_cache_init_end: + mov r0, init_hardware_hook + cmp r0, 0 + jlne [r0] + +/* STAGE 2: init necessary registers */ + +_arc_reset_stage2: + mov r0, 0 + +/* interrupt related init */ + sr r0, [AUX_IRQ_ACT] + sr r0, [AUX_IRQ_CTRL] + sr r0, [AUX_IRQ_HINT] + +/* use the new vector table to replace the old one */ +#if defined(ARC_FEATURE_SEC_PRESENT) && (SECURESHIELD_VERSION < 2) + sr exc_entry_table, [AUX_INT_VECT_BASE_S] +#else + sr exc_entry_table, [AUX_INT_VECT_BASE] +#endif + +/* init stack */ +#if ARC_FEATURE_RGF_BANKED_REGS >= 16 && ARC_FEATURE_RGF_BANKED_REGS > 1 && ARC_FEATURE_FIRQ == 1 +#if _STACKSIZE < 512 +#error "not enough stack size for irq and firq" +#endif + +/* switch to register bank1 */ + lr r0, [AUX_STATUS32] + bic r0, r0, 0x70000 + or r0, r0, 0x10000 + kflag r0 +/* set sp, gp, fp in bank1 */ + mov sp, _e_stack + mov gp, _f_sdata + mov fp, 0 +/* come back to bank0 */ + lr r0, [AUX_STATUS32] + bic r0, r0, 0x70000 + kflag r0 + mov sp, _e_stack-256 +#else + mov sp, _e_stack /* init stack pointer */ +#endif + mov gp, _f_sdata /* init small-data base register */ + mov fp, 0 /* init fp register */ + +_arc_reset_stage3: +_s3_copy_text: + mov r0, _f_text + mov r1, _load_addr_text + cmp r0, r1 + +/* if load addr == run addr, no need to copy */ + jeq _s3_copy_rodata + mov r3, _e_text +_s3_copy_text_loop: + ld.ab r2, [r1, 4] + st.ab r2, [r0, 4] + cmp r0, r3 + jlt _s3_copy_text_loop +_s3_copy_rodata: + mov r0, _f_rodata + mov r1, _load_addr_rodata + cmp r0, r1 + +/* if load addr == run addr, no need to copy */ + jeq _s3_copy_data + mov r3, _e_rodata +_s3_copy_rodata_loop: + ld.ab r2, [r1, 4] + st.ab r2, [r0, 4] + cmp r0, r3 + jlt _s3_copy_rodata_loop +_s3_copy_data: + mov r0, _f_data + mov r1, _load_addr_data + cmp r0, r1 + jeq _s3_clear_bss + +/* if load addr == run addr, no need to copy */ + mov r3, _e_data +_s3_copy_data_loop: + ld.ab r2, [r1, 4] + st.ab r2, [r0, 4] + cmp r0, r3 + jlt _s3_copy_data_loop +_s3_clear_bss: + mov r0, _f_bss + mov r1, _e_bss + cmp r0, r1 + jge _arc_reset_call_main + mov r2, 0 +_s3_clear_bss_loop: + st.ab r2, [r0, 4] + cmp r0, r1 + jlt _s3_clear_bss_loop + +/* STAGE 3: go to main */ + +_arc_reset_call_main: + +/* \todo add cpp init here */ + mov r0, init_software_hook + cmp r0, 0 + jlne [r0] +/* board level library init */ +#ifdef LIB_SECURESHIELD + jl secureshield_start +#else +/* early init of interrupt and exception */ + jl exc_int_init +#endif +/* init cache */ + jl arc_cache_init +#if defined(__MW__) + jl _init +#elif defined(__GNU__) + jl __do_global_ctors_aux + jl __do_init_array_aux +#endif + jl board_main /* board-level main */ +#if defined(__MW__) + jl _fini +#elif defined(__GNU__) + jl __do_global_dtors_aux +#endif + .global _exit_loop + .global _exit_halt + .align 4 +_exit_halt: +_exit_loop: + flag 0x1 + nop + nop + nop + b _exit_loop + +#if defined(__MW__) + .global _init, _fini + .section ".init",text +_init: + .cfa_bf _init + push %blink + .cfa_push {%blink} + + .section ".init$999999", text, 1, 2, check_text_align=0 + pop %blink + .cfa_pop {%blink} + j [%blink] + .cfa_ef + + .section ".fini", text +_fini: + .cfa_bf _fini + push %blink + .cfa_push {%blink} + + .section ".fini$999999", text, 1, 2, check_text_align=0 + pop %blink + .cfa_pop {%blink} + j [%blink] + .cfa_ef +#endif +/** @endcond */ + +/** }@*/ diff --git a/hw/mcu/arc/snps/src/hal_os_tick.c b/hw/mcu/arc/snps/src/hal_os_tick.c new file mode 100644 index 000000000..c24ec50bd --- /dev/null +++ b/hw/mcu/arc/snps/src/hal_os_tick.c @@ -0,0 +1,103 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 +#include +#include "hal/hal_os_tick.h" +#include "os/os_trace_api.h" +#include "inc/arc/arc.h" +#include "inc/arc/arc_exception.h" +#include "inc/arc/arc_timer.h" + +struct hal_os_tick +{ + uint8_t timer_num; + uint8_t vecnum; + int ticks_per_ostick; + os_time_t max_idle_ticks; + uint32_t lastocmp; +}; + +struct hal_os_tick g_hal_os_tick; + +void +os_tick_idle(os_time_t ticks) +{ + (void)ticks; +} + +static void +arc_timer_handler(void *arg) +{ + uint32_t sr; + + os_trace_enter_isr(); + arc_timer_int_clear(g_hal_os_tick.timer_num); + + OS_ENTER_CRITICAL(sr); + + /* TODO: for now, just advance one tick */ + os_time_advance(1); + + OS_EXIT_CRITICAL(sr); + os_trace_exit_isr(); +} + +void +os_tick_init(uint32_t os_ticks_per_sec, int prio) +{ + int32_t rc; + uint32_t sr; + + assert(ARC_FEATURE_CPU_CLOCK_FREQ % os_ticks_per_sec == 0); + + g_hal_os_tick.ticks_per_ostick = ARC_FEATURE_CPU_CLOCK_FREQ / + os_ticks_per_sec; + + /* Determine if timer 0 or timer 1 present */ + if (arc_timer_present(TIMER_0)) { + g_hal_os_tick.timer_num = TIMER_0; + g_hal_os_tick.vecnum = 16; + } else if (arc_timer_present(TIMER_1)) { + g_hal_os_tick.timer_num = TIMER_1; + g_hal_os_tick.vecnum = 17; + } else { + /* Must be at least timer */ + assert(0); + } + + /* disable interrupts */ + OS_ENTER_CRITICAL(sr); + + /* Set isr in vector table and enable interrupt */ + rc = int_pri_set(g_hal_os_tick.vecnum, (uint32_t)prio); + assert(rc == 0); + + rc = int_handler_install(g_hal_os_tick.vecnum, arc_timer_handler); + assert(rc == 0); + + rc = int_enable(g_hal_os_tick.vecnum); + assert(rc == 0); + + arc_timer_stop(g_hal_os_tick.timer_num); + arc_timer_start(g_hal_os_tick.timer_num, + TIMER_CTRL_IE | TIMER_CTRL_NH, + g_hal_os_tick.ticks_per_ostick); + + OS_EXIT_CRITICAL(sr); +} diff --git a/hw/mcu/arc/snps/src/hal_system.c b/hw/mcu/arc/snps/src/hal_system.c new file mode 100644 index 000000000..f45ac48c4 --- /dev/null +++ b/hw/mcu/arc/snps/src/hal_system.c @@ -0,0 +1,68 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 "hal/hal_system.h" + +/** + * Function called at startup. Called after BSS and .data initialized but + * prior to the _start function. + * + * NOTE: this function is called by both the bootloader and the application. + * If you add code here that you do not want executed in either case you need + * to conditionally compile it using the config variable BOOT_LOADER (will + * be set to 1 in case of bootloader build) + * + */ +void +hal_system_init(void) +{ +/* TDOD: anything needed here? */ +} + +void +hal_system_reset(void) +{ + while (1) { + if (hal_debugger_connected()) { + /* + * If debugger is attached, breakpoint here. + */ + asm("BRK_S"); + } +/* TODO: Reset system! */ + //NVIC_SystemReset(); + } +} + +int +hal_debugger_connected(void) +{ + return 0; +} + +/** + * hal system clock start + * + * Makes sure the LFCLK and/or HFCLK is started. + */ +void +hal_system_clock_start(void) +{ +/* TODO: do I need to deal with this? */ +} diff --git a/hw/mcu/arc/snps/src/hal_timer.c b/hw/mcu/arc/snps/src/hal_timer.c new file mode 100644 index 000000000..55fdd00bf --- /dev/null +++ b/hw/mcu/arc/snps/src/hal_timer.c @@ -0,0 +1,199 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 +#include +#include +#include +#include "hal/hal_timer.h" + +/* IRQ prototype */ +typedef void (*hal_timer_irq_handler_t)(void); + +/* TODO: port to peripheral timers */ + +/** + * hal timer init + * + * Initialize platform specific timer items + * + * @param timer_num Timer number to initialize + * @param cfg Pointer to platform specific configuration + * + * @return int 0: success; error code otherwise + */ +int +hal_timer_init(int timer_num, void *cfg) +{ + (void)timer_num; + (void)cfg; + return 0; +} + +/** + * hal timer config + * + * Configure a timer to run at the desired frequency. This starts the timer. + * + * @param timer_num + * @param freq_hz + * + * @return int + */ +int +hal_timer_config(int timer_num, uint32_t freq_hz) +{ + (void)timer_num; + (void)freq_hz; + return 0; +} + +/** + * hal timer deinit + * + * De-initialize a HW timer. + * + * @param timer_num + * + * @return int + */ +int +hal_timer_deinit(int timer_num) +{ + (void)timer_num; + return 0; +} + +/** + * hal timer get resolution + * + * Get the resolution of the timer. This is the timer period, in nanoseconds + * + * @param timer_num + * + * @return uint32_t The + */ +uint32_t +hal_timer_get_resolution(int timer_num) +{ + (void)timer_num; + return 0; +} + +/** + * hal timer read + * + * Returns the timer counter. NOTE: if the timer is a 16-bit timer, only + * the lower 16 bits are valid. If the timer is a 64-bit timer, only the + * low 32-bits are returned. + * + * @return uint32_t The timer counter register. + */ +uint32_t +hal_timer_read(int timer_num) +{ + (void)timer_num; + return 0; +} + +/** + * hal timer delay + * + * Blocking delay for n ticks + * + * @param timer_num + * @param ticks + * + * @return int 0 on success; error code otherwise. + */ +int +hal_timer_delay(int timer_num, uint32_t ticks) +{ + uint32_t until; + + until = hal_timer_read(timer_num) + ticks; + while ((int32_t)(hal_timer_read(timer_num) - until) <= 0) { + /* Loop here till finished */ + } + + return 0; +} + +/** + * + * Initialize the HAL timer structure with the callback and the callback + * argument. Also initializes the HW specific timer pointer. + * + * @param cb_func + * + * @return int + */ +int +hal_timer_set_cb(int timer_num, struct hal_timer *timer, hal_timer_cb cb_func, + void *arg) +{ + + timer->cb_func = cb_func; + timer->cb_arg = arg; + timer->link.tqe_prev = NULL; + timer->bsp_timer = NULL; + + return 0; +} + +int +hal_timer_start(struct hal_timer *timer, uint32_t ticks) +{ + int rc; + uint32_t tick; + + tick = ticks; + rc = hal_timer_start_at(timer, tick); + return rc; +} + +int +hal_timer_start_at(struct hal_timer *timer, uint32_t tick) +{ + (void)tick; + if ((timer == NULL) || (timer->link.tqe_prev != NULL) || + (timer->cb_func == NULL)) { + return EINVAL; + } + + return 0; +} + +/** + * hal timer stop + * + * Stop a timer. + * + * @param timer + * + * @return int + */ +int +hal_timer_stop(struct hal_timer *timer) +{ + if (timer == NULL) { + return EINVAL; + } + return 0; +} diff --git a/hw/mcu/arc/snps/src/hal_watchdog.c b/hw/mcu/arc/snps/src/hal_watchdog.c new file mode 100644 index 000000000..930fc22eb --- /dev/null +++ b/hw/mcu/arc/snps/src/hal_watchdog.c @@ -0,0 +1,39 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 +#include "hal/hal_watchdog.h" + +int +hal_watchdog_init(uint32_t expire_msecs) +{ + (void)expire_msecs; + return (0); +} + +void +hal_watchdog_enable(void) +{ +} + +void +hal_watchdog_tickle(void) +{ +} + diff --git a/hw/mcu/arc/snps/syscfg.yml b/hw/mcu/arc/snps/syscfg.yml new file mode 100644 index 000000000..5057f978b --- /dev/null +++ b/hw/mcu/arc/snps/syscfg.yml @@ -0,0 +1,19 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you 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. +# + +# Package: hw/mcu/arc/snps diff --git a/hw/mcu/arc/src/ext/sdk/README.md b/hw/mcu/arc/src/ext/sdk/README.md new file mode 100644 index 000000000..7614d85e5 --- /dev/null +++ b/hw/mcu/arc/src/ext/sdk/README.md @@ -0,0 +1,22 @@ +# embARC BSP for EMSK +## Introduction +The embARC Board support Package (BSP) for DesignWare? ARC? EM Starter Kit (EMSK) is a software distribution aimed at facilitating the development and evaluation of embedded systems based on ARCv2 processors. + +It is designed to provide a board support package for ARC EMSK users by defining consistent and simple software interfaces to the processors and onboard devices. + +## embARC BSP Features +embARC BSP architecture is shown in the block diagram below. + +![embARC BSP Architecture](doc/documents/pic/embarc_bsp_arch.jpg) + +embARC BSP provides ARC Hardware Abstraction Layer (HAL), device HAL and driver implementation for UART, I2C, GPIO and SPI. A group of driver implementations for DesignWare IP peripherals are provided in embARC BSP for EMSK. + +[ARC Development Tools](https://www.synopsys.com/designware-ip/processor-solutions/arc-processors/arc-development-tools.html) are supported in embARC BSP, [Premium MetaWare Development Toolkit (>=2016.12)](http://www.synopsys.com/dw/ipdir.php?ds=sw_metaware) and [Opensource ARC GNU IDE(>=2016.09)](https://github.com/foss-for-synopsys-dwc-arc-processors/toolchain/releases). + +### embARC BSP & embARC OSP + +embARC BSP code is originated from [embARC OSP](https://github.com/foss-for-synopsys-dwc-arc-processors/embarc_osp). The code are reorganized with the same ARC HAL, device HAL and driver implementations for DesignWare IP peripherals. The operating system layer, common library layer, middleware layer and applications are not included in embARC BSP. The code in embARC BSP is independent with build system. It can be ported to various build system easily. The lightweight makefile and Eclipse IDE are both supported in embARC BSP as reference. + +## Get Started with embARC BSP +* Use [Premium MetaWare Development Toolkit (>=2016.12)](http://www.synopsys.com/dw/ipdir.php?ds=sw_metaware) in embARC BSP +* Use [Opensource ARC GNU IDE(>=2016.09)](https://github.com/foss-for-synopsys-dwc-arc-processors/toolchain/releases) in embARC BSP diff --git a/hw/mcu/arc/src/ext/sdk/arc/arc_cache.c b/hw/mcu/arc/src/ext/sdk/arc/arc_cache.c new file mode 100644 index 000000000..632a3e329 --- /dev/null +++ b/hw/mcu/arc/src/ext/sdk/arc/arc_cache.c @@ -0,0 +1,420 @@ +/* ------------------------------------------ + * Copyright (c) 2016, Synopsys, Inc. All rights reserved. + + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + + * 1) Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + + * 2) 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. + + * 3) Neither the name of the Synopsys, Inc., nor the names of its contributors may + * be used to endorse or promote products derived from this software without + * specific prior written permission. + + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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. + * + * \version 2016.05 + * \date 2014-07-15 + * \author Wayne Ren(Wei.Ren@synopsys.com) +--------------------------------------------- */ + +/** + * \file + * \ingroup ARC_HAL_MISC_CACHE + * \brief implementation of cache related functions + */ + +#include "inc/arc/arc_cache.h" + +#define DIV_ROUND_UP(x, y) (((x) + (y) - 1) / (y)) + + +struct cache_config { + uint8_t ver; /* version */ + uint8_t assoc; /* Cache Associativity */ + uint16_t line; /* cache line/block size */ + uint32_t capacity; /* capacity */ +}; + + +static struct cache_config icache_config, dcache_config; + +/** + * \brief invalidate multi instruction cache lines + * + * \param[in] start_addr start address in instruction cache + * \param[in] size the bytes to be invalidated + * \return 0, succeeded, -1, failed + */ +int32_t icache_invalidate_mlines(uint32_t start_addr, uint32_t size) +{ + if (!icache_available()) return -1; + + if ((size == 0) || (size > icache_config.capacity)) { + return -1; + } + + uint32_t end_addr; + uint32_t line_size; + uint32_t status; + + line_size = (uint32_t)(icache_config.line); + end_addr = start_addr + size - 1; + start_addr &= (uint32_t)(~(line_size - 1)); + + status = cpu_lock_save(); + do { + _arc_aux_write(AUX_IC_IVIL, start_addr); + Asm("nop_s"); + Asm("nop_s"); + Asm("nop_s"); + start_addr += line_size; + } while (start_addr <= end_addr); + cpu_unlock_restore(status); + + return 0; +} + +/** + * \brief lock multi lines in instruction cache + * + * \param[in] start_addr start address in instruction cache + * \param[in] size the bytes to be locked + * \return 0, succeeded, -1, failed (cache already locked or other reasons) + */ +int32_t icache_lock_mlines(uint32_t start_addr, uint32_t size) +{ + if (!icache_available()) return -1; + + if ((size == 0) || (size > icache_config.capacity)) { + return -1; + } + + uint32_t end_addr; + uint32_t line_size; + uint32_t status; + int32_t ercd = 0; + + line_size = (uint32_t)(icache_config.line); + end_addr = start_addr + size - 1; + start_addr &= (uint32_t)(~(line_size - 1)); + + status = cpu_lock_save(); + do { + _arc_aux_write(AUX_IC_LIL, start_addr); + if(_arc_aux_read(AUX_IC_CTRL) & IC_CTRL_OP_SUCCEEDED) { + start_addr += line_size; + } else { + ercd = -1; /* the operation failed */ + break; + } + } while (start_addr <= end_addr); + cpu_unlock_restore(status); + + return ercd; +} + +/** + * \brief directly write icache internal ram + * + * \param[in] cache_addr, icache internal address(way+index+offset) + * \param[in] tag cache tag to write (tag+lock bit+valid bit) + * \param[in] data cache data to write + * \return 0, succeeded, -1, failed + */ +int32_t icache_direct_write(uint32_t cache_addr, uint32_t tag, uint32_t data) +{ + if (!icache_available()) return -1; + + if (_arc_aux_read(AUX_IC_CTRL) & IC_CTRL_INDIRECT_ACCESS) { + return -1; + } + _arc_aux_write(AUX_IC_RAM_ADDR, cache_addr); + _arc_aux_write(AUX_IC_TAG, tag ); + _arc_aux_write(AUX_IC_DATA, data); + + return 0; +} + +/** + * \brief directly read icache internal ram + * + * \param[in] cache_addr, icache internal address(way+index+offset) + * \param[out] tag cache tag to read (tag+index+lock bit+valid bit) + * \param[out] data cache data to read + * \return 0, succeeded, -1, failed + */ +int32_t icache_direct_read(uint32_t cache_addr, uint32_t *tag, uint32_t *data) +{ + if (!icache_available()) return -1; + + if (_arc_aux_read(AUX_IC_CTRL) & IC_CTRL_INDIRECT_ACCESS) { + return -1; + } + _arc_aux_write(AUX_IC_RAM_ADDR, cache_addr); + *tag = _arc_aux_read(AUX_IC_TAG); + *data = _arc_aux_read(AUX_IC_DATA); + + return 0; +} + +/** + * \brief indirectly read icache internal ram + * + * \param[in] mem_addr, memory address + * \param[out] tag cache tag to read + * \param[out] data cache data to read + * \return 0, succeeded, -1, failed + */ +int32_t icache_indirect_read(uint32_t mem_addr, uint32_t *tag, uint32_t *data) +{ + if (!icache_available()) return -1; + + if (!(_arc_aux_read(AUX_IC_CTRL) & IC_CTRL_INDIRECT_ACCESS)) { + return -1; + } + _arc_aux_write(AUX_IC_RAM_ADDR, mem_addr); + if(_arc_aux_read(AUX_IC_CTRL) & IC_CTRL_OP_SUCCEEDED) { + *tag = _arc_aux_read(AUX_IC_TAG); + *data = _arc_aux_read(AUX_IC_DATA); + } else { + return -1; /* the specified memory is not in icache */ + } + return 0; + } + +/** + * \brief invalidate multi data cache lines + * + * \param[in] start_addr start address in data cache + * \param[in] size the bytes to be invalidated + * \return 0, succeeded, -1, failed + */ +int32_t dcache_invalidate_mlines(uint32_t start_addr, uint32_t size) +{ + if (!dcache_available()) return -1; + + uint32_t end_addr; + uint32_t line_size; + uint32_t status; + + if ((size == 0) || (size > dcache_config.capacity)) { + return -1; + } + + line_size = (uint32_t)(dcache_config.line); + end_addr = start_addr + size - 1; + start_addr &= (uint32_t)(~(line_size - 1)); + + status = cpu_lock_save(); + do { + _arc_aux_write(AUX_DC_IVDL, start_addr); + Asm("nop_s"); + Asm("nop_s"); + Asm("nop_s"); + /* wait for flush completion */ + while (_arc_aux_read(AUX_DC_CTRL) & DC_CTRL_FLUSH_STATUS); + start_addr += line_size; + } while (start_addr <= end_addr); + cpu_unlock_restore(status); + + return 0; + +} + +/** + * \brief flush multi lines in data cache + * + * \param[in] start_addr start address + * \param[in] size the bytes to be flushed + * \return 0, succeeded, -1, failed + */ +int32_t dcache_flush_mlines(uint32_t start_addr, uint32_t size) +{ + if (!dcache_available()) return -1; + + if ((size == 0) || (size > dcache_config.capacity)) { + return -1; + } + + uint32_t end_addr; + uint32_t line_size; + uint32_t status; + + line_size = (uint32_t)(dcache_config.line); + end_addr = start_addr + size - 1; + start_addr &= (uint32_t)(~(line_size - 1)); + + status = cpu_lock_save(); + do { + _arc_aux_write(AUX_DC_FLDL, start_addr); + Asm("nop_s"); + Asm("nop_s"); + Asm("nop_s"); + /* wait for flush completion */ + while (_arc_aux_read(AUX_DC_CTRL) & DC_CTRL_FLUSH_STATUS); + start_addr += line_size; + } while (start_addr <= end_addr); + cpu_unlock_restore(status); + + return 0; +} + +/** + * \brief lock multi lines in data cache + * + * \param[in] start_addr start address in data cache + * \param[in] size the bytes to be locked + * \return 0, succeeded, -1, failed + */ +int32_t dcache_lock_mlines(uint32_t start_addr, uint32_t size) +{ + if (!dcache_available()) return -1; + + if ((size == 0) || (size > dcache_config.capacity)) { + return -1; + } + + uint32_t end_addr; + uint32_t line_size; + uint32_t status; + int32_t ercd = 0; + + line_size = (uint32_t)(dcache_config.line); + end_addr = start_addr + size - 1; + start_addr &= (uint32_t)(~(line_size - 1)); + + status = cpu_lock_save(); + do { + _arc_aux_write(AUX_DC_LDL, start_addr); + Asm("nop_s"); + if(_arc_aux_read(AUX_DC_CTRL) & DC_CTRL_OP_SUCCEEDED) { + start_addr += line_size; + } else { + ercd = -1; /* the operation failed */ + break; + } + } while (start_addr <= end_addr); + cpu_unlock_restore(status); + + return ercd; +} + +/** + * \brief directly write dcache internal ram + * + * \param[in] cache_addr, dcache internal address(way+index+offset) + * \param[in] tag cache tag to write + * \param[in] data cache data to write + * \return 0, succeeded, -1, failed + */ +int32_t dcache_direct_write(uint32_t cache_addr, uint32_t tag, uint32_t data) +{ + if (!dcache_available()) return -1; + + if (_arc_aux_read(AUX_DC_CTRL) & DC_CTRL_INDIRECT_ACCESS) { + return -1; + } + _arc_aux_write(AUX_DC_RAM_ADDR, cache_addr); + _arc_aux_write(AUX_DC_TAG, tag); + _arc_aux_write(AUX_DC_DATA, data); + + return 0; +} + +/** + * \brief directly read dcache internal ram + * + * \param[in] cache_addr, dcache internal address(way+index+offset) + * \param[out] tag cache tag to read + * \param[out] data cache data to read + * \return 0, succeeded, -1, failed + */ +int32_t dcache_direct_read(uint32_t cache_addr, uint32_t *tag, uint32_t *data) +{ + if (!dcache_available()) return -1; + + if (_arc_aux_read(AUX_DC_CTRL) & DC_CTRL_INDIRECT_ACCESS) { + return -1; + } + _arc_aux_write(AUX_DC_RAM_ADDR, cache_addr); + *tag = _arc_aux_read(AUX_DC_TAG); + *data = _arc_aux_read(AUX_DC_DATA); + + return 0; +} + +/** + * \brief indirectly read dcache internal ram + * + * \param[in] mem_addr, memory address(tag+index+offset) + * \param[out] tag cache tag to read + * \param[out] data cache data to read + * \return 0, succeeded, -1, failed + */ +int32_t dcache_indirect_read(uint32_t mem_addr, uint32_t *tag, uint32_t *data) +{ + if (!dcache_available()) return -1; + + if (!(_arc_aux_read(AUX_DC_CTRL) & DC_CTRL_INDIRECT_ACCESS)) { + return -1; + } + _arc_aux_write(AUX_DC_RAM_ADDR, mem_addr); + if(_arc_aux_read(AUX_DC_CTRL) & DC_CTRL_OP_SUCCEEDED) { + *tag = _arc_aux_read(AUX_DC_TAG); + *data = _arc_aux_read(AUX_DC_DATA); + } else { + return -1; /* the specified memory is not in dcache */ + } + return 0; + } + +/** + * \brief initialize cache + * 1. invalidate icache and dcache + * 2. Only support ARCv2 cache + */ +void arc_cache_init(void) +{ + uint32_t build_cfg; + + build_cfg = _arc_aux_read(AUX_BCR_D_CACHE); + + dcache_config.ver = build_cfg & 0xff; + + if (dcache_config.ver >= 0x04) { /* ARCv2 */ + dcache_enable(DC_CTRL_DISABLE_FLUSH_LOCKED | + DC_CTRL_INDIRECT_ACCESS | DC_CTRL_INVALID_FLUSH); + dcache_invalidate(); + dcache_config.assoc = 1 << ((build_cfg >> 8) & 0xf); + dcache_config.capacity = 512 << ((build_cfg >> 12) & 0xf); + dcache_config.line = 16 << ((build_cfg >> 16) & 0xf); + } + + build_cfg = _arc_aux_read(AUX_BCR_I_CACHE); + + icache_config.ver = build_cfg & 0xff; + + if (icache_config.ver >= 0x04) { /* ARCv2 */ + icache_config.assoc = 1 << ((build_cfg >> 8) & 0xf); + icache_config.capacity = 512 << ((build_cfg >> 12) & 0xf); + icache_config.line = 8 << ((build_cfg >> 16) & 0xf); + + icache_enable(IC_CTRL_IC_ENABLE); + icache_invalidate(); + } + +} diff --git a/hw/mcu/arc/src/ext/sdk/arc/arc_exc_asm.S b/hw/mcu/arc/src/ext/sdk/arc/arc_exc_asm.S new file mode 100644 index 000000000..76b2cd3e9 --- /dev/null +++ b/hw/mcu/arc/src/ext/sdk/arc/arc_exc_asm.S @@ -0,0 +1,202 @@ +/* ------------------------------------------ + * Copyright (c) 2016, Synopsys, Inc. All rights reserved. + + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + + * 1) Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + + * 2) 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. + + * 3) Neither the name of the Synopsys, Inc., nor the names of its contributors may + * be used to endorse or promote products derived from this software without + * specific prior written permission. + + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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. + * + * \version 2016.05 + * \date 2014-07-15 + * \author Wayne Ren(Wei.Ren@synopsys.com) +--------------------------------------------- */ + +/** + * \file + * \ingroup ARC_HAL_EXCEPTION_CPU + * \brief assembly part of exception and interrupt processing + */ + +/** + * \addtogroup ARC_HAL_EXCEPTION_CPU + * @{ + */ + +/* function documentation */ +/** + * \fn void exc_entry_cpu(void) + * \brief default entry of CPU exceptions, such as TLB miss and swap. + * + * \fn void exc_entry_int(void) + * \brief normal interrupt exception entry. + * In default, all interrupt exceptions are installed with normal entry. + * If FIRQ is required, exc_entry_firq should be the entry. + * + * \fn void exc_entry_firq(void) + * \brief firq exception entry + */ +/** }@ */ + +/** @cond EXCEPTION_ASM */ + +#define __ASSEMBLY__ +#include "embARC_BSP_config.h" +#include "inc/arc/arc.h" +#include "inc/arc/arc_asm_common.h" + + .file "arc_exc_asm.S" + +/* entry for cpu exception handling */ + .text + .global exc_entry_cpu + .weak exc_entry_cpu + .align 4 +exc_entry_cpu: + + EXCEPTION_PROLOGUE + + mov r3, sp /* as exception handler's para(exc_frame) */ + +/* exc_nest_count +1 */ + ld r0, [exc_nest_count] + add r0, r0, 1 + st r0, [exc_nest_count] + +/* find the exception cause */ + lr r0, [AUX_ECR] + lsr r0, r0, 16 + bmsk r0, r0, 7 + mov r1, exc_int_handler_table + ld.as r2, [r1, r0] + + mov r0, r3 + jl [r2] /* jump to exception handler where interrupts are not allowed! */ + +/* interrupts are not allowed */ +exc_return: + +/* exc_nest_count -1 */ + ld r0, [exc_nest_count] + sub r0, r0, 1 + st r0, [exc_nest_count] + + EXCEPTION_EPILOGUE + rtie + + +/****** entry for normal interrupt exception handling ******/ + .global exc_entry_int + .weak exc_entry_int + .align 4 +exc_entry_int: + clri /* disable interrupt */ + +#if ARC_FEATURE_FIRQ == 1 +#if ARC_FEATURE_RGF_NUM_BANKS > 1 + lr r0, [AUX_IRQ_ACT] /* check whether it is P0 interrupt */ + btst r0, 0 + bnz exc_entry_firq +#else + PUSH r10 + lr r10, [AUX_IRQ_ACT] + btst r10, 0 + POP r10 + bnz exc_entry_firq +#endif +#endif + INTERRUPT_PROLOGUE /* save scratch regs, this will be affected */ + + +/* exc_nest_count +1 */ + ld r0, [exc_nest_count] + add r0, r0, 1 + st r0, [exc_nest_count] + + + lr r0, [AUX_IRQ_CAUSE] + mov r1, exc_int_handler_table + ld.as r2, [r1, r0] /* r2 = _kernel_exc_tbl + irqno *4 */ + +/* for the case of software triggered interrupt */ + lr r3, [AUX_IRQ_HINT] + cmp r3, r0 + bne.d irq_hint_handled + xor r3, r3, r3 + sr r3, [AUX_IRQ_HINT] +irq_hint_handled: + seti /* enable higher priority interrupt */ + + mov r0, sp + jl [r2] /* jump to interrupt handler */ + +/* no interrupts are allowed from here */ +int_return: + clri /* disable interrupt */ + +/* exc_nest_count -1 */ + ld r0, [exc_nest_count] + sub r0, r0, 1 + st r0, [exc_nest_count] + + INTERRUPT_EPILOGUE + rtie + +/****** entry for fast irq exception handling ******/ + .global exc_entry_firq + .weak exc_entry_firq + .align 4 +exc_entry_firq: + clri /* disable interrupt */ + SAVE_FIQ_EXC_REGS + +/* exc_nest_count +1 */ + ld r0, [exc_nest_count] + add r0, r0, 1 + st r0, [exc_nest_count] + + lr r0, [AUX_IRQ_CAUSE] + mov r1, exc_int_handler_table + ld.as r2, [r1, r0] /* r2 = _kernel_exc_tbl + irqno *4 */ + +/* for the case of software triggered interrupt */ + lr r3, [AUX_IRQ_HINT] + cmp r3, r0 + bne.d firq_hint_handled + xor r3, r3, r3 + sr r3, [AUX_IRQ_HINT] +firq_hint_handled: + + jl [r2] /* jump to interrupt handler */ + +/* no interrupts are allowed from here */ +firq_return: + +/* exc_nest_count -1 */ + ld r0, [exc_nest_count] + sub r0, r0, 1 + st r0, [exc_nest_count] + + RESTORE_FIQ_EXC_REGS + rtie + +/** @endcond */ diff --git a/hw/mcu/arc/src/ext/sdk/arc/arc_exception.c b/hw/mcu/arc/src/ext/sdk/arc/arc_exception.c new file mode 100644 index 000000000..30dddd6c6 --- /dev/null +++ b/hw/mcu/arc/src/ext/sdk/arc/arc_exception.c @@ -0,0 +1,514 @@ +/* ------------------------------------------ + * Copyright (c) 2016, Synopsys, Inc. All rights reserved. + + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + + * 1) Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + + * 2) 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. + + * 3) Neither the name of the Synopsys, Inc., nor the names of its contributors may + * be used to endorse or promote products derived from this software without + * specific prior written permission. + + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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. + * + * \version 2016.05 + * \date 2014-07-15 + * \author Wayne Ren(Wei.Ren@synopsys.com) +--------------------------------------------- */ + +/** + * \file + * \ingroup ARC_HAL_EXCEPTION_CPU ARC_HAL_EXCEPTION_INTERRUPT + * \brief C Implementation of exception and interrupt management + */ +#include "inc/arc/arc_exception.h" +#include "inc/arc/arc_cache.h" + +//#define DBG_LESS +//#include "embARC_debug.h" + +/** + * \addtogroup ARC_HAL_EXCEPTION_CPU + * @{ + * \var exc_entry_table + * \brief exception entry table + * + * install exception entry table to ARC_AUX_INT_VECT_BASE in startup. + * According to ARCv2 ISA, vectors are fetched in instruction space and thus + * may be present in ICCM, Instruction Cache, or + * main memory accessed by instruction fetch logic. + * So it is put into a specific section .vector. + * + * Please note that the exc_entry_table maybe cached in ARC. Some functions is + * defined in .s files. + * + */ + +/** + * \ingroup ARC_HAL_EXCEPTION_CPU + * \brief default cpu exception handler + * \param p_excinf pointer to the exception frame + */ +static void exc_handler_default(void *p_excinf) +{ + uint32_t excpt_cause_reg = 0; + uint32_t excpt_ret_reg = 0; + uint32_t exc_no = 0; + + excpt_cause_reg = _arc_aux_read(AUX_ECR); + excpt_ret_reg = _arc_aux_read(AUX_ERRET); + exc_no = (excpt_cause_reg >> 16) & 0xff; + + //dbg_printf(DBG_LESS_INFO, "default cpu exception handler\r\n"); + //dbg_printf(DBG_LESS_INFO, "exc_no:%d, last sp:0x%08x, ecr:0x%08x, eret:0x%08x\r\n", + //exc_no, (uint32_t)p_excinf, excpt_cause_reg, excpt_ret_reg); +#if SECURESHIELD_VERSION == 2 + while (1); +#else + Asm("kflag 1"); +#endif +} + + +/** + * \ingroup ARC_HAL_EXCEPTION_INTERRUPT + * \brief default interrupt handler + * \param[in] p_excinf information for interrupt handler + */ +static void int_handler_default(void *p_excinf) +{ + uint32_t int_cause_reg = 0; + + int_cause_reg = _arc_aux_read(AUX_IRQ_CAUSE); + //dbg_printf(DBG_LESS_INFO, "default interrupt handler\r\n"); + //dbg_printf(DBG_LESS_INFO, "last sp:0x%08x, icause:0x%08x\r\n", (uint32_t)p_excinf, int_cause_reg); +#if SECURESHIELD_VERSION == 2 + while (1); +#else + Asm("kflag 1"); +#endif +} + +__attribute__ ((aligned(1024), section(".vector"))) +EXC_ENTRY exc_entry_table[NUM_EXC_ALL] = { + [0] = _arc_reset, + [1 ... NUM_EXC_CPU-1] = exc_entry_cpu, + [NUM_EXC_CPU ... NUM_EXC_ALL-1] = exc_entry_int + }; +/** + * \var exc_int_handler_table + * \brief the cpu exception and interrupt exception handler table + * called in exc_entry_default and exc_entry_int + */ +EXC_HANDLER exc_int_handler_table[NUM_EXC_ALL] = { + [0 ... NUM_EXC_CPU-1] = exc_handler_default, + [NUM_EXC_CPU ... NUM_EXC_ALL-1] = int_handler_default +}; + +/** + * \var exc_nest_count + * \brief the counter for exc/int processing, =0 no int/exc + * >1 in int/exc processing + * @} + */ +uint32_t exc_nest_count; + +typedef struct aux_irq_ctrl_field { + /* note: little endian */ + uint32_t save_nr_gpr_pairs: 5; /** Indicates number of general-purpose register pairs saved, from 0 to 8/16 */ + uint32_t res: 4; /** Reserved */ + uint32_t save_blink: 1; /** Indicates whether to save and restore BLINK */ + uint32_t save_lp_regs: 1; /** Indicates whether to save and restore loop registers (LP_COUNT, LP_START, LP_END) */ + uint32_t save_u_to_u: 1; /** Indicates if user context is saved to user stack */ + uint32_t res2: 1; /** Reserved */ + uint32_t save_idx_regs: 1; /** Indicates whether to save and restore code-density registers (EI_BASE, JLI_BASE, LDI_BASE) */ + uint32_t res3: 18; /** Reserved */ +} aux_irq_ctrl_field_t; + +typedef union { + aux_irq_ctrl_field_t bits; + uint32_t value; +} aux_irq_ctrl_t; + +/** + * \ingroup ARC_HAL_EXCEPTION_CPU ARC_HAL_EXCEPTION_INTERRUPT + * \brief intialize the exception and interrupt handling + */ +void exc_int_init(void) +{ + uint32_t i; + uint32_t status; + aux_irq_ctrl_t ictrl; + + ictrl.value = 0; + +#ifndef ARC_FEATURE_RF16 + ictrl.bits.save_nr_gpr_pairs = 6; /* r0 to r11 (r12 saved manually) */ +#else + ictrl.bits.save_nr_gpr_pairs = 3; /* r0 to r3, r10, r11 */ +#endif + ictrl.bits.save_blink = 1; + ictrl.bits.save_lp_regs = 1; /* LP_COUNT, LP_START, LP_END */ + ictrl.bits.save_u_to_u = 0; /* user ctxt saved on kernel stack */ + ictrl.bits.save_idx_regs = 1; /* JLI, LDI, EI */ + + status = arc_lock_save(); + for (i = NUM_EXC_CPU; i < NUM_EXC_ALL; i++) { + /* interrupt level triggered, disabled, priority is the lowest */ + _arc_aux_write(AUX_IRQ_SELECT, i); + _arc_aux_write(AUX_IRQ_ENABLE, 0); + _arc_aux_write(AUX_IRQ_TRIGGER, 0); +#if defined(ARC_FEATURE_SEC_PRESENT) && (SECURESHIELD_VERSION < 2) + _arc_aux_write(AUX_IRQ_PRIORITY, (1 << AUX_IRQ_PRIORITY_BIT_S)|(INT_PRI_MAX - INT_PRI_MIN)); +#else + _arc_aux_write(AUX_IRQ_PRIORITY, INT_PRI_MAX - INT_PRI_MIN); +#endif + } + _arc_aux_write(AUX_IRQ_CTRL, ictrl.value); + + arc_unlock_restore(status); + + /** ipm should be set after cpu unlock restore to avoid reset of the status32 value */ + arc_int_ipm_set((INT_PRI_MAX - INT_PRI_MIN)); +} + +/** + * \ingroup ARC_HAL_EXCEPTION_CPU + * \brief install a CPU exception entry + * \param[in] excno exception number + * \param[in] entry the entry of exception to install + */ +int32_t exc_entry_install(const uint32_t excno, EXC_ENTRY entry) +{ + uint32_t status; + + EXC_ENTRY *table = (EXC_ENTRY *)_arc_aux_read(AUX_INT_VECT_BASE); + + if (excno < NUM_EXC_ALL && entry != NULL + && table[excno] != entry) { + status = cpu_lock_save(); + /* directly write to mem, as arc gets exception handler from mem not from cache */ + /* FIXME, here maybe icache is dirty, need to be invalidated */ + table[excno] = entry; + + if (_arc_aux_read(AUX_BCR_D_CACHE) > 0x2) { + /* dcache is available */ + dcache_flush_line((uint32_t)&table[excno]); + } + + if (_arc_aux_read(AUX_BCR_D_CACHE) > 0x2) { + /* icache is available */ + icache_invalidate_line((uint32_t)&table[excno]); + } + cpu_unlock_restore(status); + return 0; + } + return -1; +} + +/** + * \ingroup ARC_HAL_EXCEPTION_CPU + * \brief get the installed CPU exception entry + * \param[in] excno exception number + * \return the installed CPU exception entry + */ +EXC_ENTRY exc_entry_get(const uint32_t excno) +{ + if (excno < NUM_EXC_ALL) { + return exc_entry_table[excno]; + } + return NULL; +} + +/** + * \ingroup ARC_HAL_EXCEPTION_CPU + * \brief install an exception handler + * \param[in] excno exception number + * \param[in] handler the handler of exception to install + */ +int32_t exc_handler_install(const uint32_t excno, EXC_HANDLER handler) +{ + if (excno < NUM_EXC_ALL && handler != NULL) { + exc_int_handler_table[excno] = handler; + return 0; + } + + return -1; +} + +/** + * \ingroup ARC_HAL_EXCEPTION_CPU + * \brief get the installed exception handler + * \param[in] excno exception number + * \return the installed exception handler or NULL + */ +EXC_HANDLER exc_handler_get(const uint32_t excno) +{ + if (excno < NUM_EXC_ALL) { + return exc_int_handler_table[excno]; + } + + return NULL; +} + + +#ifndef EMBARC_OVERRIDE_ARC_INTERRUPT_MANAGEMENT +/** + * \brief disable the specific interrupt + * + * \param[in] intno interrupt number + */ +int32_t int_disable(const uint32_t intno) +{ + if (intno >= NUM_EXC_CPU && intno < NUM_EXC_ALL) { + arc_int_disable(intno); + return 0; + } + + return -1; +} + +/** + * \brief enable the specific int + * + * \param[in] intno interrupt number + */ +int32_t int_enable(const uint32_t intno) +{ + if (intno >= NUM_EXC_CPU && intno < NUM_EXC_ALL) { + arc_int_enable(intno); + return 0; + } + + return -1; +} + +/** + * \brief check whether the specific int is enabled + * + * \param[in] intno interrupt number + * \return 0 disabled, 1 enabled, < 0 error + */ +int32_t int_enabled(const uint32_t intno) +{ + if (intno >= NUM_EXC_CPU && intno < NUM_EXC_ALL) { + _arc_aux_write(AUX_IRQ_SELECT, intno); + return _arc_aux_read(AUX_IRQ_ENABLE); + } + + return -1; +} + +/** + * \brief get the interrupt priority mask + * + * \returns interrupt priority mask, negative num + */ +int32_t int_ipm_get(void) +{ + return ((int32_t)arc_int_ipm_get() + INT_PRI_MIN); +} + + +/** + * \brief set the interrupt priority mask + * + * \param[in] intpri interrupt priority + */ +int32_t int_ipm_set(int32_t intpri) +{ + if (intpri >= INT_PRI_MIN && intpri <= INT_PRI_MAX) { + intpri = intpri - INT_PRI_MIN; + arc_int_ipm_set(intpri); + return 0; + } + + return -1; +} + + +/** + * \brief get current interrupt priority mask + * + * \param[in] intno interrupt number + * \return <0 interrupt priority, 0 error + */ +int32_t int_pri_get(const uint32_t intno) +{ + if (intno >= NUM_EXC_CPU && intno < NUM_EXC_ALL) { + return (int32_t)arc_int_pri_get(intno) + INT_PRI_MIN; + } + + return 0; +} + + +/** + * \brief set interrupt priority + * + * \param[in] intno interrupt number + * \param[in] intpri interrupt priority + * \return <0 error, 0 ok + */ +int32_t int_pri_set(const uint32_t intno, int32_t intpri) +{ + uint32_t status; + + if (intno >= NUM_EXC_CPU && intno < NUM_EXC_ALL) { + status = cpu_lock_save(); + intpri = intpri - INT_PRI_MIN; + arc_int_pri_set(intno,(uint32_t)intpri); + cpu_unlock_restore(status); + return 0; + } + return -1; +} + +/** + * \brief set interrupt secure or not secure + * This function is valid in secureshield v2 + * \param[in] intno interrupt number + * \param[in] secure, 0 for normal, >0 for secure + * \return <0 error, 0 ok + */ +int32_t int_secure_set(const uint32_t intno, uint32_t secure) +{ + if (intno >= NUM_EXC_CPU && intno < NUM_EXC_ALL) { + arc_int_secure_set(intno, secure); + return 0; + } + return -1; + +} + + +/** + * \brief probe the pending status of interrupt + * + * \param[in] intno interrupt number + * + * \returns 1 pending, 0 no pending, -1 error + */ +int32_t int_probe(const uint32_t intno) +{ + if (intno >= NUM_EXC_CPU && intno < NUM_EXC_ALL) { + return arc_int_probe(intno); + } + return -1; +} + + +/** + * \brief trigger the interrupt in software + * + * \param[in] intno interrupt number + * \return 0 ok, -1 error + */ +int32_t int_sw_trigger(const uint32_t intno) +{ + if (intno >= NUM_EXC_CPU && intno < NUM_EXC_ALL) { + arc_int_sw_trigger(intno); + return 0; + } + return -1; +} + +/** + * \brief config the interrupt level triggered or pulse triggered + * + * \param[in] intno interrupt number + * \param[in] level, 0-level trigger, 1-pulse triggered + * \return 0 ok, -1 error + */ +int32_t int_level_config(const uint32_t intno, const uint32_t level) +{ + if (intno >= NUM_EXC_CPU && intno < NUM_EXC_ALL) { + arc_int_level_config(intno, level); + return 0; + } + return -1; +} + + +/** + * \brief lock cpu, disable interrupts + */ +void cpu_lock(void) +{ + arc_lock(); +} + +/** + * \brief unlock cpu, enable interrupts to happen + */ +void cpu_unlock(void) +{ + arc_unlock(); +} + +/** + * \brief lock cpu and return status + * + * \returns cpu status + */ +uint32_t cpu_lock_save(void) +{ + return arc_lock_save(); +} + +/** + * \brief unlock cpu with the specific status + * + * \param[in] status cpu status saved by cpu_lock_save + */ +void cpu_unlock_restore(const uint32_t status) +{ + arc_unlock_restore(status); +} + +/** + * \ingroup ARC_HAL_EXCEPTION_INTERRUPT + * \brief install an interrupt handler + * \param[in] intno interrupt number + * \param[in] handler interrupt handler to install + */ +int32_t int_handler_install(const uint32_t intno, INT_HANDLER handler) +{ + /*!< \todo parameter check ? */ + if (intno >= NUM_EXC_CPU) { + return exc_handler_install(intno, handler); + } + + return -1; +} + +/** + * \ingroup ARC_HAL_EXCEPTION_INTERRUPT + * \brief get the installed an interrupt handler + * \param[in] intno interrupt number + * \return the installed interrupt handler or NULL + */ +INT_HANDLER int_handler_get(const uint32_t intno) +{ + if (intno >= NUM_EXC_CPU) { + return exc_handler_get(intno); + } + + return NULL; +} +#endif /* EMBARC_OVERRIDE_ARC_INTERRUPT_MANAGEMENT */ diff --git a/hw/mcu/arc/src/ext/sdk/arc/arc_timer.c b/hw/mcu/arc/src/ext/sdk/arc/arc_timer.c new file mode 100644 index 000000000..3d0c4b4f8 --- /dev/null +++ b/hw/mcu/arc/src/ext/sdk/arc/arc_timer.c @@ -0,0 +1,211 @@ +/* ------------------------------------------ + * Copyright (c) 2016, Synopsys, Inc. All rights reserved. + + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + + * 1) Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + + * 2) 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. + + * 3) Neither the name of the Synopsys, Inc., nor the names of its contributors may + * be used to endorse or promote products derived from this software without + * specific prior written permission. + + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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. + * + * \version 2016.05 + * \date 2014-07-15 + * \author Wayne Ren(Wei.Ren@synopsys.com) +--------------------------------------------- */ + +/** + * \file + * \ingroup ARC_HAL_MISC_TIMER + * \brief implementation of internal timer related functions + * \todo RTC support should be improved if RTC is enabled + */ +#include "inc/arc/arc_timer.h" +#include "inc/arc/arc.h" +#include "inc/arc/arc_builtin.h" + +/** + * \brief check whether the specific timer present + * \param[in] no timer number + * \retval 1 present + * \retval 0 not present + */ +int32_t arc_timer_present(const uint32_t no) +{ + uint32_t bcr = _arc_aux_read(AUX_BCR_TIMERS); + switch (no) { + case TIMER_0: + bcr = (bcr >> 8) & 1; + break; + case TIMER_1: + bcr = (bcr >> 9) & 1; + break; + case TIMER_RTC: + bcr = (bcr >> 10) & 1; + break; + default: + bcr = 0; + /* illegal argument so return false */ + break; + } + + return (int)bcr; +} + +/** + * \brief start the specific timer + * \param[in] no timer number + * \param[in] mode timer mode + * \param[in] val timer limit value (not for RTC) + * \return 0 success, -1 failure + */ +int32_t arc_timer_start(const uint32_t no, const uint32_t mode, const uint32_t val) +{ + if (arc_timer_present(no) == 0) { + return -1; + } + + switch (no) { + case TIMER_0: + _arc_aux_write(AUX_TIMER0_CTRL, 0); + _arc_aux_write(AUX_TIMER0_LIMIT, val); + _arc_aux_write(AUX_TIMER0_CTRL, mode); + _arc_aux_write(AUX_TIMER0_CNT, 0); + break; + case TIMER_1: + _arc_aux_write(AUX_TIMER1_CTRL, 0); + _arc_aux_write(AUX_TIMER1_LIMIT, val); + _arc_aux_write(AUX_TIMER1_CTRL, mode); + _arc_aux_write(AUX_TIMER1_CNT, 0); + break; + case TIMER_RTC: + _arc_aux_write(AUX_RTC_CTRL, mode); + break; + default: + return -1; + } + + return 0; +} + +/** + * \brief stop and clear the specific timer + * + * \param[in] no timer number + * \return 0 success, -1 failure + */ +int32_t arc_timer_stop(const uint32_t no) +{ + if (arc_timer_present(no) == 0) { + return -1; + } + + switch (no) { + case TIMER_0 : + _arc_aux_write(AUX_TIMER0_CTRL, 0); + _arc_aux_write(AUX_TIMER0_LIMIT,0); + _arc_aux_write(AUX_TIMER0_CNT, 0); + break; + case TIMER_1: + _arc_aux_write(AUX_TIMER1_CTRL, 0); + _arc_aux_write(AUX_TIMER1_LIMIT,0); + _arc_aux_write(AUX_TIMER1_CNT, 0); + break; + case TIMER_RTC: + _arc_aux_write(AUX_RTC_CTRL, TIMER_RTC_CLEAR); + break; + default: + return -1; + } + + return 0; +} + +/** + * \brief get timer current tick + * + * \param[in] no timer number + * \param[out] val, timer value + * \return 0 success, -1 failure + */ +int32_t arc_timer_current(const uint32_t no, void *val) +{ + if (arc_timer_present(no) == 0) { + return -1; + } + + switch (no) { + case TIMER_0 : + *((uint32_t *)val) = _arc_aux_read(AUX_TIMER0_CNT); + break; + case TIMER_1 : + *((uint32_t *)val) = _arc_aux_read(AUX_TIMER1_CNT); + break; + case TIMER_RTC: + *((uint64_t *)val) = _arc_aux_read(AUX_RTC_LOW); + break; + default : + return -1; + } + + return 0; +} + +/** + * \brief clear the interrupt pending bit of timer + * + * \param[in] no timer number + * \return 0 success, -1 failure + */ +int32_t arc_timer_int_clear(const uint32_t no) +{ + uint32_t val; + + if (arc_timer_present(no) == 0) { + return -1; + } + + switch (no) { + case TIMER_0 : + val = _arc_aux_read(AUX_TIMER0_CTRL); + val &= ~TIMER_CTRL_IP; + _arc_aux_write(AUX_TIMER0_CTRL, val); + break; + case TIMER_1 : + val = _arc_aux_read(AUX_TIMER1_CTRL); + val &= ~TIMER_CTRL_IP; + _arc_aux_write(AUX_TIMER1_CTRL, val); + break; + default : + return -1; + } + + return 0; +} + +/** + * \brief init internal timer + */ +void arc_timer_init(void) +{ + arc_timer_stop(TIMER_0); + arc_timer_stop(TIMER_1); + arc_timer_stop(TIMER_RTC); +} diff --git a/hw/mcu/arc/src/ext/sdk/arc/startup/arc_cxx_support.c b/hw/mcu/arc/src/ext/sdk/arc/startup/arc_cxx_support.c new file mode 100644 index 000000000..af842fddc --- /dev/null +++ b/hw/mcu/arc/src/ext/sdk/arc/startup/arc_cxx_support.c @@ -0,0 +1,168 @@ +/* + * Copyright (c) 2012-2014 Wind River Systems, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* ------------------------------------------ + * Copyright (c) 2015, Synopsys, Inc. All rights reserved. + + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + + * 1) Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + + * 2) 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. + + * 3) Neither the name of the Synopsys, Inc., nor the names of its contributors may + * be used to endorse or promote products derived from this software without + * specific prior written permission. + + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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. + * + * \version 2016.05 + * \date 2016-03-02 + * \author Wayne Ren(wei.ren@synopsys.com) +--------------------------------------------- */ +#include "embARC_BSP_config.h" +#if defined(__GNU__) +/* embARC's GNU C++ support takes reference from Zephyr (cpp_xxx.c) */ + +/** + * @file - Constructor module + * @brief + * The ctors section contains a list of function pointers that execute the + * C++ constructors of static global objects. These must be executed before + * the application's main() routine. + * + * NOTE: Not all compilers put those function pointers into the ctors section; + * some put them into the init_array section instead. + */ + +/* What a constructor function pointer looks like */ + +typedef void (*CtorFuncPtr)(void); + +/* Constructor function pointer list is generated by the linker script. */ + +extern CtorFuncPtr __CTOR_LIST__[]; +extern CtorFuncPtr __CTOR_END__[]; + +/** + * + * @brief Invoke all C++ style global object constructors + * + * This routine is invoked before the execution of the + * application's main(). + */ +void __do_global_ctors_aux(void) +{ + unsigned int nCtors; + + nCtors = (unsigned int)__CTOR_LIST__[0]; + + while (nCtors >= 1) { + __CTOR_LIST__[nCtors--](); + } +} + +typedef void (*DtorFuncPtr)(void); + +extern DtorFuncPtr __DTOR_LIST__[]; +extern DtorFuncPtr __DTOR_END__[]; + +/** + * + * @brief Invoke all C++ style global object destructors + * + * This routine is invoked after the execution of the + * application's main(). + */ +void __do_global_dtors_aux(void) +{ + unsigned int nDtors; + unsigned int i; + + nDtors = (unsigned int)__DTOR_LIST__[0]; + i = 0; + + while (i <= nDtors) { + __DTOR_LIST__[i++](); + } +} + +void *__dso_handle = 0; + +/** + * @brief Register destructor for a global object + * + * @param destructor the global object destructor function + * @param objptr global object pointer + * @param dso Dynamic Shared Object handle for shared libraries + * + * Function does nothing at the moment, assuming the global objects + * do not need to be deleted + * + * @return N/A + */ +int __cxa_atexit(void (*destructor)(void *), void *objptr, void *dso) +{ + return 0; +} + +typedef void (*func_ptr)(void); + +extern func_ptr __init_array_start[0]; +extern func_ptr __init_array_end[0]; + +/** + * @brief Execute initialization routines referenced in .init_array section + * + * @return N/A + */ +void __do_init_array_aux(void) +{ + for (func_ptr *func = __init_array_start; + func < __init_array_end; + func++) { + (*func)(); + } +} + +/** + * @brief Stub for pure virtual functions + * + * This routine is needed for linking C++ code that uses pure virtual + * functions. + * + * @return N/A + */ +void __cxa_pure_virtual(void) +{ + while (1) { + ; + } +} +#endif diff --git a/hw/mcu/arc/src/ext/sdk/arc/startup/arc_startup.S b/hw/mcu/arc/src/ext/sdk/arc/startup/arc_startup.S new file mode 100644 index 000000000..00092d3e1 --- /dev/null +++ b/hw/mcu/arc/src/ext/sdk/arc/startup/arc_startup.S @@ -0,0 +1,266 @@ +/* ------------------------------------------ + * Copyright (c) 2016, Synopsys, Inc. All rights reserved. + + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + + * 1) Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + + * 2) 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. + + * 3) Neither the name of the Synopsys, Inc., nor the names of its contributors may + * be used to endorse or promote products derived from this software without + * specific prior written permission. + + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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. + * + * \version 2016.05 + * \date 2014-07-15 + * \author Wayne Ren(Wei.Ren@synopsys.com) +--------------------------------------------- */ + +/** + * \file + * \ingroup ARC_HAL_STARTUP + * \brief assembly part of startup process + */ + +/** + * \addtogroup ARC_HAL_STARTUP + * @{ + */ +/** @cond STARTUP_ASM */ + +#define __ASSEMBLY__ +#include "embARC_BSP_config.h" +#include "inc/arc/arc.h" + + .file "arc_startup.S" + +.weak _f_sdata /* start of small data, defined in link script */ +.weak init_hardware_hook /* app hardware init hook */ +.weak init_software_hook /* app software init hook */ + +.extern board_main +.extern exc_entry_table + +/* initial vector table */ + .section .init_vector, "a" + .long _arc_reset + .section .init_bootstrap, "ax" + .global _arc_reset + .global _start + .align 4 +_start: +_arc_reset: +_arc_reset_stage1: + kflag STATUS32_RESET_VALUE + +/* STAGE 1 */ + +/* necessary hardware should be done first to speed up initialization + 1. system clk + 2. mem controller must be initialized before any access to external + mem. + 3. others +*/ +_arc_cache_init_start: + lr r0, [AUX_BCR_D_CACHE] + cmp r0, 2 + /* invalidate dcache */ + jle _arc_icache_init + mov r0, 1 + sr r0, [AUX_DC_IVDC] + sr r0, [AUX_DC_CTRL] +_arc_icache_init: + lr r0, [AUX_BCR_I_CACHE] + cmp r0, 2 + jle _arc_cache_init_end + /* invalidate icache */ + mov r0, 1 + sr r0, [AUX_IC_IVIC] + nop_s + nop_s + nop_s + sr r0, [AUX_IC_CTRL] + +_arc_cache_init_end: + mov r0, init_hardware_hook + cmp r0, 0 + jlne [r0] + +/* STAGE 2: init necessary registers */ + +_arc_reset_stage2: + mov r0, 0 + +/* interrupt related init */ + sr r0, [AUX_IRQ_ACT] + sr r0, [AUX_IRQ_CTRL] + sr r0, [AUX_IRQ_HINT] + +/* use the new vector table to replace the old one */ +#if defined(ARC_FEATURE_SEC_PRESENT) && (SECURESHIELD_VERSION < 2) + sr exc_entry_table, [AUX_INT_VECT_BASE_S] +#else + sr exc_entry_table, [AUX_INT_VECT_BASE] +#endif + +/* init stack */ +#if ARC_FEATURE_RGF_BANKED_REGS >= 16 && ARC_FEATURE_RGF_BANKED_REGS > 1 && ARC_FEATURE_FIRQ == 1 +#if _STACKSIZE < 512 +#error "not enough stack size for irq and firq" +#endif + +/* switch to register bank1 */ + lr r0, [AUX_STATUS32] + bic r0, r0, 0x70000 + or r0, r0, 0x10000 + kflag r0 +/* set sp, gp, fp in bank1 */ + mov sp, _e_stack + mov gp, _f_sdata + mov fp, 0 +/* come back to bank0 */ + lr r0, [AUX_STATUS32] + bic r0, r0, 0x70000 + kflag r0 + mov sp, _e_stack-256 +#else + mov sp, _e_stack /* init stack pointer */ +#endif + mov gp, _f_sdata /* init small-data base register */ + mov fp, 0 /* init fp register */ + +_arc_reset_stage3: +_s3_copy_text: + mov r0, _f_text + mov r1, _load_addr_text + cmp r0, r1 + +/* if load addr == run addr, no need to copy */ + jeq _s3_copy_rodata + mov r3, _e_text +_s3_copy_text_loop: + ld.ab r2, [r1, 4] + st.ab r2, [r0, 4] + cmp r0, r3 + jlt _s3_copy_text_loop +_s3_copy_rodata: + mov r0, _f_rodata + mov r1, _load_addr_rodata + cmp r0, r1 + +/* if load addr == run addr, no need to copy */ + jeq _s3_copy_data + mov r3, _e_rodata +_s3_copy_rodata_loop: + ld.ab r2, [r1, 4] + st.ab r2, [r0, 4] + cmp r0, r3 + jlt _s3_copy_rodata_loop +_s3_copy_data: + mov r0, _f_data + mov r1, _load_addr_data + cmp r0, r1 + jeq _s3_clear_bss + +/* if load addr == run addr, no need to copy */ + mov r3, _e_data +_s3_copy_data_loop: + ld.ab r2, [r1, 4] + st.ab r2, [r0, 4] + cmp r0, r3 + jlt _s3_copy_data_loop +_s3_clear_bss: + mov r0, _f_bss + mov r1, _e_bss + cmp r0, r1 + jge _arc_reset_call_main + mov r2, 0 +_s3_clear_bss_loop: + st.ab r2, [r0, 4] + cmp r0, r1 + jlt _s3_clear_bss_loop + +/* STAGE 3: go to main */ + +_arc_reset_call_main: + +/* \todo add cpp init here */ + mov r0, init_software_hook + cmp r0, 0 + jlne [r0] +/* board level library init */ +#ifdef LIB_SECURESHIELD + jl secureshield_start +#else +/* early init of interrupt and exception */ + jl exc_int_init +#endif +/* init cache */ + jl arc_cache_init +#if defined(__MW__) + jl _init +#elif defined(__GNU__) + jl __do_global_ctors_aux + jl __do_init_array_aux +#endif + jl board_main /* board-level main */ +#if defined(__MW__) + jl _fini +#elif defined(__GNU__) + jl __do_global_dtors_aux +#endif + .global _exit_loop + .global _exit_halt + .align 4 +_exit_halt: +_exit_loop: + flag 0x1 + nop + nop + nop + b _exit_loop + +#if defined(__MW__) + .global _init, _fini + .section ".init",text +_init: + .cfa_bf _init + push %blink + .cfa_push {%blink} + + .section ".init$999999", text, 1, 2, check_text_align=0 + pop %blink + .cfa_pop {%blink} + j [%blink] + .cfa_ef + + .section ".fini", text +_fini: + .cfa_bf _fini + push %blink + .cfa_push {%blink} + + .section ".fini$999999", text, 1, 2, check_text_align=0 + pop %blink + .cfa_pop {%blink} + j [%blink] + .cfa_ef +#endif +/** @endcond */ + +/** }@*/ diff --git a/hw/mcu/arc/src/ext/sdk/board/board.h b/hw/mcu/arc/src/ext/sdk/board/board.h new file mode 100644 index 000000000..bfade6dce --- /dev/null +++ b/hw/mcu/arc/src/ext/sdk/board/board.h @@ -0,0 +1,68 @@ +/* ------------------------------------------ + * Copyright (c) 2017, Synopsys, Inc. All rights reserved. + + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + + * 1) Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + + * 2) 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. + + * 3) Neither the name of the Synopsys, Inc., nor the names of its contributors may + * be used to endorse or promote products derived from this software without + * specific prior written permission. + + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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. + * + * \version 2017.03 + * \date 2014-07-03 + * \author Huaqi Fang(Huaqi.Fang@synopsys.com) +--------------------------------------------- */ +/** + * + * \file + * \ingroup BOARD_COMMON + * \brief common board header file + * \details + * - This header file will contain board related settings for different boards. + * - Each board configurations are put in its own header file, like emsk/emsk.h + * - If you want to change the configuration, you need to go to related header file, e.g. + * if you want to change EMSK board settings, you need to go to emsk/emsk.h + * - In embARC 2015.05, all the settings are in this board.h, but now it moved to related board header file + */ + +/** + * \addtogroup BOARD_COMMON + * @{ + */ +#ifndef _EMBARC_BOARD_H_ +#define _EMBARC_BOARD_H_ + +#include "embARC_BSP_config.h" +/** + * \todo add comments and documents to describe the macros + * \note the following macros must use the same name, because + * they are used by middleware and other applications + */ +/** here is a sample of EMSK board resource definitions */ +#ifdef BOARD_EMSK +#include "board/emsk/emsk.h" +#endif /* BOARD_EMSK */ + +/** you can add your board configuration as BOARD_EMSK defined up */ + +#endif /* _EMBARC_BOARD_H_ */ + +/** @} end of group BOARD_COMMON */ diff --git a/hw/mcu/arc/src/ext/sdk/board/emsk/common/emsk_init.c b/hw/mcu/arc/src/ext/sdk/board/emsk/common/emsk_init.c new file mode 100644 index 000000000..0c12cafeb --- /dev/null +++ b/hw/mcu/arc/src/ext/sdk/board/emsk/common/emsk_init.c @@ -0,0 +1,116 @@ +/* ------------------------------------------ + * Copyright (c) 2016, Synopsys, Inc. All rights reserved. + + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + + * 1) Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + + * 2) 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. + + * 3) Neither the name of the Synopsys, Inc., nor the names of its contributors may + * be used to endorse or promote products derived from this software without + * specific prior written permission. + + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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. + * + * \version 2016.05 + * \date 2014-07-31 + * \author Wayne Ren(Wei.Ren@synopsys.com) +--------------------------------------------- */ +/** + * \defgroup BOARD_EMSK_COMMON_INIT EMSK Common Init Module + * \ingroup BOARD_EMSK_COMMON + * \brief EMSK Board Common Init Module + * \details + * EMSK timer/gpio/interrupt init process. Device-driver installation is done while + * getting the device object for the first time. + */ + +/** + * \file + * \ingroup BOARD_EMSK_COMMON_INIT + * \brief common emsk init module + */ + +/** + * \addtogroup BOARD_EMSK_COMMON_INIT + * @{ + */ +#include "inc/arc/arc_builtin.h" +#include "inc/arc/arc.h" +#include "inc/arc/arc_timer.h" + +#include "board/emsk/emsk.h" +#include "board/emsk/common/emsk_timer.h" +#include "board/emsk/common/mux.h" + +#ifdef ARC_FEATURE_DMP_PERIPHERAL +#define PERIPHERAL_BASE ARC_FEATURE_DMP_PERIPHERAL +#else +#define PERIPHERAL_BASE _arc_aux_read(AUX_DMP_PERIPHERAL) +#endif + +/** + * \brief emsk-related mux io init + */ +static void emsk_mux_init(void) +{ + MUX_REG *mux_regs; + + mux_regs = (MUX_REG *)(PERIPHERAL_BASE|REL_REGBASE_PINMUX); + mux_init(mux_regs); + + /** + * + Please refer to corresponding EMSK User Guide for detailed information + * -> Appendix: A Hardware Functional Description + * -> Pmods Configuration summary + * + Set up pin-multiplexer of all PMOD connections + * - PM1 J1: Upper row as UART 0, lower row as SPI Slave + * - PM2 J2: IIC 0 and run/halt signals + * - PM3 J3: GPIO Port A and Port C + * - PM4 J4: IIC 1 and Port D + * - PM5 J5: Upper row as SPI Master, lower row as Port A + * - PM6 J6: Upper row as SPI Master, lower row as Port A + */ + set_pmod_mux(mux_regs, PM1_UR_UART_0 | PM1_LR_SPI_S \ + | PM2_I2C_HRI \ + | PM3_GPIO_AC \ + | PM4_I2C_GPIO_D \ + | PM5_UR_SPI_M1 | PM5_LR_GPIO_A \ + | PM6_UR_SPI_M0 | PM6_LR_GPIO_A ); + + /** + * PM1 upper row as UART + * UM4:RXD, UM3:TXD + * UM2:RTS_N, UM1:CTS_N + */ + set_uart_map(mux_regs, 0x9c); +} + +/** + * \brief Board init routine MUST be called in each application + * \note It is better to disable interrupts when calling this function + * remember to enable interrupt when you want to use them + */ +void board_init(void) +{ + arc_timer_init(); + emsk_mux_init(); + emsk_gpio_init(); + emsk_timer_init(); +} + +/** @} end of group BOARD_EMSK_COMMON_INIT */ diff --git a/hw/mcu/arc/src/ext/sdk/board/emsk/common/emsk_timer.c b/hw/mcu/arc/src/ext/sdk/board/emsk/common/emsk_timer.c new file mode 100644 index 000000000..e61c3b8a1 --- /dev/null +++ b/hw/mcu/arc/src/ext/sdk/board/emsk/common/emsk_timer.c @@ -0,0 +1,189 @@ +/* ------------------------------------------ + * Copyright (c) 2016, Synopsys, Inc. All rights reserved. + + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + + * 1) Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + + * 2) 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. + + * 3) Neither the name of the Synopsys, Inc., nor the names of its contributors may + * be used to endorse or promote products derived from this software without + * specific prior written permission. + + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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. + * + * \version 2016.05 + * \date 2014-07-31 + * \author Wayne Ren(Wei.Ren@synopsys.com) +--------------------------------------------- */ +/** + * \defgroup BOARD_EMSK_COMMON_TIMER EMSK Common Timer Module + * \ingroup BOARD_EMSK_COMMON + * \brief provide basic board timer-related functions + * \details + * Provide a 1 MS (default) timer interrupt, + * provide a 64-bit counter value (no clear) count in the timer interrupt, + * provide MS-precision delay, with OS enabled-support delay + */ + +/** + * \file + * \ingroup BOARD_EMSK_COMMON_TIMER + * \brief provide emsk board timer-related functions + */ + +/** + * \addtogroup BOARD_EMSK_COMMON_TIMER + * @{ + */ +#include "inc/arc/arc_builtin.h" +#include "inc/arc/arc.h" +#include "inc/arc/arc_timer.h" +#include "inc/arc/arc_exception.h" + +#include "board/emsk/emsk.h" + +#define MAX_SYS_COUNTER_VALUE (0xffffffff) + +#ifndef BOARD_SYS_TIMER_HZ +#define BOARD_SYS_TIMER_HZ (1000) +#endif + +/** emsk board timer interrupt reset count */ +static uint32_t cyc_hz_count = (BOARD_CPU_CLOCK / BOARD_SYS_TIMER_HZ); + +/** emsk board timer counter in timer interrupt */ +volatile uint64_t gl_emsk_sys_hz_cnt = 0; +/** emsk board 1ms counter */ +volatile uint32_t gl_emsk_ms_cnt = 0; + +#define HZ_COUNT_CONV(precision, base) ((precision)/(base)) + +/** + * \brief Update timer counter and other MS period operation + * in cycling interrupt and must be called periodically. When the OS timer + * interrupt is in conflict with the bare-metal timer interrupt, + * put this function into the OS timer interrupt + * \param[in] precision interrupt-period precision in Hz + */ +void board_timer_update(uint32_t precision) +{ + static uint32_t sys_hz_update = 0; + static uint32_t sys_ms_update = 0; + uint32_t hz_conv = 0; + + /** count sys hz */ + hz_conv = HZ_COUNT_CONV(precision, BOARD_SYS_TIMER_HZ); + sys_hz_update ++; + if (sys_hz_update >= hz_conv) { + sys_hz_update = 0; + gl_emsk_sys_hz_cnt ++; + } + + /** count ms */ + hz_conv = HZ_COUNT_CONV(precision, BOARD_SYS_TIMER_MS_HZ); + sys_ms_update ++; + if (sys_ms_update >= hz_conv) { + sys_ms_update = 0; + gl_emsk_ms_cnt ++; + } +} + +/** + * \brief emsk bare-metal timer interrupt. + * the Interrupt frequency is based on the defined \ref BOARD_SYS_TIMER_HZ + */ +static void emsk_timer_isr(void *ptr) +{ + arc_timer_int_clear(BOARD_SYS_TIMER_ID); + + board_timer_update(BOARD_SYS_TIMER_HZ); +} + +/** + * \brief init bare-metal emsk board timer and interrupt + * \details + * This function is called in \ref board_init, and + * it initializes the 1-MS timer interrupt for bare-metal mode + */ +void emsk_timer_init(void) +{ + if (arc_timer_present(BOARD_SYS_TIMER_ID)) { + int_disable(BOARD_SYS_TIMER_INTNO); /* disable first then enable */ + int_handler_install(BOARD_SYS_TIMER_INTNO, emsk_timer_isr); + arc_timer_start(BOARD_SYS_TIMER_ID, TIMER_CTRL_IE|TIMER_CTRL_NH, cyc_hz_count); /* start 1ms timer interrupt */ + + int_enable(BOARD_SYS_TIMER_INTNO); + } +} + +/** + * \brief get current cpu hardware ticks + * \retval hardware ticks count in 64 bit format + */ +uint64_t board_get_hwticks(void) +{ + uint32_t sub_ticks; + uint64_t total_ticks; + arc_timer_current(TIMER_0, &sub_ticks); + + total_ticks = (uint64_t)OSP_GET_CUR_MS() * (BOARD_CPU_CLOCK/BOARD_SYS_TIMER_HZ); + total_ticks += (uint64_t)sub_ticks; + + return total_ticks; +} + +/** + * \brief get current passed us since timer init + * \retval us count in 64 bit format + */ +uint64_t board_get_cur_us(void) +{ + uint32_t sub_us; + uint64_t total_us; + arc_timer_current(TIMER_0, &sub_us); + + sub_us = ((uint64_t)sub_us * 1000000) / BOARD_CPU_CLOCK; + total_us = ((uint64_t)OSP_GET_CUR_MS()) * 1000 + (uint64_t)sub_us; + + return total_us; +} + +/** + * \brief provide MS delay function + * \details + * this function needs a 1-MS timer interrupt to work. + * For bare-metal, it is implemented in this file. + * For OS, you must call \ref board_timer_update in + * the OS 1-MS timer interrupt when the bare-metal timer interrupt + * is not ready + * \param[in] ms MS to delay + * \param[in] os_compat Enable or disable + * When this delay is enabled, use the OS delay function, if one is provided. + * See \ref OSP_DELAY_OS_COMPAT_ENABLE and + * \ref OSP_DELAY_OS_COMPAT_DISABLE + */ +void board_delay_ms(uint32_t ms, uint8_t os_compat) +{ + uint64_t start_us, us_delayed; + + us_delayed = ((uint64_t)ms * 1000); + start_us = board_get_cur_us(); + while ((board_get_cur_us() - start_us) < us_delayed); +} + +/** @} end of group BOARD_EMSK_COMMON_TIMER */ diff --git a/hw/mcu/arc/src/ext/sdk/board/emsk/common/emsk_timer.h b/hw/mcu/arc/src/ext/sdk/board/emsk/common/emsk_timer.h new file mode 100644 index 000000000..5e86a3c6a --- /dev/null +++ b/hw/mcu/arc/src/ext/sdk/board/emsk/common/emsk_timer.h @@ -0,0 +1,63 @@ +/* ------------------------------------------ + * Copyright (c) 2016, Synopsys, Inc. All rights reserved. + + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + + * 1) Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + + * 2) 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. + + * 3) Neither the name of the Synopsys, Inc., nor the names of its contributors may + * be used to endorse or promote products derived from this software without + * specific prior written permission. + + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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. + * + * \version 2016.05 + * \date 2014-07-31 + * \author Wayne Ren(Wei.Ren@synopsys.com) +--------------------------------------------- */ +/** + * \file + * \ingroup BOARD_EMSK_COMMON_TIMER + * \brief emsk timer functions header + */ + +/** + * \addtogroup BOARD_EMSK_COMMON_TIMER + * @{ + */ +#ifndef _EMSK_TIMER_ +#define _EMSK_TIMER_ + +#include "inc/embARC_toolchain.h" + +#ifdef __cplusplus +extern "C" { +#endif + +extern volatile uint64_t gl_emsk_sys_hz_cnt; +extern volatile uint32_t gl_emsk_ms_cnt; + +extern void emsk_timer_init(void); + +#ifdef __cplusplus +} +#endif + +#endif /* _EMSK_TIMER_ */ + +/** @} end of group BOARD_EMSK_COMMON_TIMER */ diff --git a/hw/mcu/arc/src/ext/sdk/board/emsk/common/mux.c b/hw/mcu/arc/src/ext/sdk/board/emsk/common/mux.c new file mode 100644 index 000000000..4cec2754e --- /dev/null +++ b/hw/mcu/arc/src/ext/sdk/board/emsk/common/mux.c @@ -0,0 +1,116 @@ +/* ------------------------------------------ + * Copyright (c) 2016, Synopsys, Inc. All rights reserved. + + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + + * 1) Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + + * 2) 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. + + * 3) Neither the name of the Synopsys, Inc., nor the names of its contributors may + * be used to endorse or promote products derived from this software without + * specific prior written permission. + + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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. + * + * \version 2016.05 + * \date 2014-07-07 + * \author Huaqi Fang(Huaqi.Fang@synopsys.com) +--------------------------------------------- */ +/** + * \defgroup BOARD_EMSK_DRV_MUX EMSK Mux Driver + * \ingroup BOARD_EMSK_DRIVER + * \brief EMSK Mux Controller Driver + * \details + * Mux controller is the hardware external PMOD port pin connection + * controller, it can distribute the external port pins into different + * functions like general input/output, spi, iic, uart and so on. + */ + +/** + * \file + * \ingroup BOARD_EMSK_DRV_MUX + * \brief emsk mux controller driver + */ + +/** + * \addtogroup BOARD_EMSK_DRV_MUX + * @{ + */ +#include "board/emsk/common/mux_hal.h" +#include "board/emsk/common/mux.h" + +static MUX_REG *mux_ctrl_regs = (MUX_REG *)0; + +/** initialize i2c controller and set slave device address */ +void mux_init(MUX_REG *mux_regs) +{ + // Initialize Mux controller registers by default values + mux_regs[PMOD_MUX_CTRL] = PMOD_MUX_CTRL_DEFAULT; + mux_regs[SPI_MAP_CTRL] = SPI_MAP_CTRL_DEFAULT; + mux_regs[UART_MAP_CTRL] = UART_MAP_CTRL_DEFAULT; + mux_ctrl_regs = mux_regs; +} + +/** Get mux ctrl register pointer, only valid after mux_init */ +MUX_REG *get_mux_regs(void) +{ + return mux_ctrl_regs; +} + +/** set PMOD muxer scheme */ +void set_pmod_mux(MUX_REG *mux_regs, uint32_t val) +{ + mux_regs[PMOD_MUX_CTRL] = val; +} + +/** get PMOD muxer scheme */ +uint32_t get_pmod_mux(MUX_REG *mux_regs) +{ + return (uint32_t) mux_regs[PMOD_MUX_CTRL]; +} + +/** set PMOD muxer scheme */ +void change_pmod_mux(MUX_REG *mux_regs, uint32_t val, uint32_t change_bits) +{ + mux_regs[PMOD_MUX_CTRL] = ((mux_regs[PMOD_MUX_CTRL] & ~change_bits) | val); +} + +/** set SPI connection scheme */ +void set_spi_map(MUX_REG *mux_regs, uint32_t val) +{ + mux_regs[SPI_MAP_CTRL] = val; +} + +/** get SPI connection scheme */ +uint32_t get_spi_map(MUX_REG *mux_regs) +{ + return (uint32_t) mux_regs[SPI_MAP_CTRL]; +} + +/** set UART connection scheme */ +void set_uart_map(MUX_REG *mux_regs, uint32_t val) +{ + mux_regs[UART_MAP_CTRL] = val; +} + +/** get UART connection scheme */ +uint32_t get_uart_map(MUX_REG *mux_regs) +{ + return (uint32_t) mux_regs[UART_MAP_CTRL]; +} +/** @} end of group BOARD_EMSK_DRV_MUX */ + diff --git a/hw/mcu/arc/src/ext/sdk/board/emsk/common/mux.h b/hw/mcu/arc/src/ext/sdk/board/emsk/common/mux.h new file mode 100644 index 000000000..3e3101e92 --- /dev/null +++ b/hw/mcu/arc/src/ext/sdk/board/emsk/common/mux.h @@ -0,0 +1,186 @@ +/* ------------------------------------------ + * Copyright (c) 2016, Synopsys, Inc. All rights reserved. + + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + + * 1) Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + + * 2) 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. + + * 3) Neither the name of the Synopsys, Inc., nor the names of its contributors may + * be used to endorse or promote products derived from this software without + * specific prior written permission. + + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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. + * + * \version 2016.05 + * \date 2014-07-07 + * \author Huaqi Fang(Huaqi.Fang@synopsys.com) +--------------------------------------------- */ +/** + * \file + * \ingroup BOARD_EMSK_DRV_MUX + * \brief header file of emsk mux controller driver + */ + +/** + * \addtogroup BOARD_EMSK_DRV_MUX + * @{ + */ +#ifndef _MUX_H_ +#define _MUX_H_ + +#include "inc/embARC_toolchain.h" + +#define BIT0 (0) +#define BIT1 (1) +#define BIT2 (2) +#define BIT3 (3) +#define PM1_OFFSET (0) +#define PM2_OFFSET (4) +#define PM3_OFFSET (8) +#define PM4_OFFSET (12) +#define PM5_OFFSET (16) +#define PM6_OFFSET (20) +#define PM7_OFFSET (24) + +#define PM1_MASK (0xf << PM1_OFFSET) +#define PM2_MASK (0xf << PM2_OFFSET) +#define PM3_MASK (0xf << PM3_OFFSET) +#define PM4_MASK (0xf << PM4_OFFSET) +#define PM5_MASK (0xf << PM5_OFFSET) +#define PM6_MASK (0xf << PM6_OFFSET) +#define PM7_MASK (0xf << PM7_OFFSET) + + +#define SPI_MAP_NORMAL (0) +#define SPI_MAP_LOOPBACK (1) + +#define UART_MAP_TYPE4 (0xE4) +#define UART_MAP_TYPE3 (0x6C) + +/** + * \name Default pin muxer settings + * @{ + */ +#define PMOD_MUX_CTRL_DEFAULT (0) /*!< all pins are configured as GPIO inputs */ +#define SPI_MAP_CTRL_DEFAULT (SPI_MAP_NORMAL) /*!< normal SPI mode */ +#define UART_MAP_CTRL_DEFAULT (UART_MAP_TYPE4) /*!< TYPE4 PMOD compatible */ +/** @} end of name */ + +/** + * \name PMOD 1 Multiplexor + * @{ + */ +#define PM1_UR_GPIO_C ((0 << BIT0) << PM1_OFFSET) /*!< Pmod1[4:1] are connected to DW GPIO Port C[11:8] */ +#define PM1_UR_UART_0 ((1 << BIT0) << PM1_OFFSET) /*!< Pmod1[4:1] are connected to DW UART0 signals */ + +#define PM1_LR_GPIO_A ((0 << BIT2) << PM1_OFFSET) /*!< Pmod1[10:7] are connected to DW GPIO Port A[11:8] */ +#define PM1_LR_SPI_S ((1 << BIT2) << PM1_OFFSET) /*!< Pmod1[10:7] are connected to DW SPI Slave signals */ +/** @} end of name */ + + +/** + * \name PMOD 2 Multiplexor + * @{ + */ +#define PM2_GPIO_AC ((0 << BIT0) << PM2_OFFSET) /*!< Pmod2[4:1] are connected to DW GPIO Port C[15:12], + Pmod2[10:7] are connected to DW GPIO Port A[15:12] */ + +#define PM2_I2C_HRI ((1 << BIT0) << PM2_OFFSET) /*!< connect I2C to Pmod2[4:1] and halt/run interface to Pmod2[10:7] */ +/** @} end of name */ + + +/** + * \name PMOD 3 Multiplexor + * @{ + */ +#define PM3_GPIO_AC ((0 << BIT0) << PM3_OFFSET) /*!< Pmod3[4:1] are connected to DW GPIO Port C[19:16], + Pmod3[10:7] are connected to DW GPIO Port A[19:16] */ + +#define PM3_I2C_GPIO_D ((1 << BIT0) << PM3_OFFSET) /*!< Pmod3[4:3] are connected to DW I2C signals, + Pmod3[2:1] are connected to DW GPIO Port D[1:0], + Pmod3[10:7] are connected to DW GPIO Port D[3:2] */ +/** @} end of name */ + + +/** + * \name PMOD 4 Multiplexor + * @{ + */ +#define PM4_GPIO_AC ((0 << BIT0) << PM4_OFFSET) /*!< Pmod4[4:1] are connected to DW GPIO Port C[23:20], + Pmod4[10:7] are connected to DW GPIO Port A[23:20] */ + +#define PM4_I2C_GPIO_D ((1 << BIT0) << PM4_OFFSET) /*!< Pmod4[4:3] are connected to DW I2C signals, + Pmod4[2:1] are connected to DW GPIO Port D[5:4], + Pmod4[10:7] are connected to DW GPIO Port D[7:6] */ +/** @} end of name */ + +/** + * \name PMOD 5 Multiplexor + * @{ + */ +#define PM5_UR_GPIO_C ((0 << BIT0) << PM5_OFFSET) /*!< Pmod5[4:1] are connected to DW GPIO Port C[27:24] */ +#define PM5_UR_SPI_M1 ((1 << BIT0) << PM5_OFFSET) /*!< Pmod5[4:1] are connected to DW SPI Master signals using CS1_N */ + +#define PM5_LR_GPIO_A ((0 << BIT2) << PM5_OFFSET) /*!< Pmod5[10:7] are connected to DW GPIO Port A[27:24] */ +#define PM5_LR_SPI_M2 ((1 << BIT2) << PM5_OFFSET) /*!< Pmod5[10:7] are connected to DW SPI Master signals using CS2_N */ +/** @} end of name */ + + +/** + * \name PMOD 6 Multiplexor + * @{ + */ +#define PM6_UR_GPIO_C ((0 << BIT0) << PM6_OFFSET) /*!< Pmod6[4:1] are connected to DW GPIO Port C[31:28] */ +#define PM6_UR_SPI_M0 ((1 << BIT0) << PM6_OFFSET) /*!< Pmod6[4:1] are connected to DW SPI Master signals using CS0_N */ + +#define PM6_LR_GPIO_A ((0 << BIT2) << PM6_OFFSET) /*!< Pmod6[10:7] are connected to DW GPIO Port A[31:28] */ + +#define PM6_LR_CSS_STAT ((1 << BIT2) << PM6_OFFSET) /*!< Pmod6[8:7] are connected to the DW SPI Master chip select signals CS1_N and CS2_N, + Pmod6[6:5] are connected to the ARC EM halt and sleep status signals */ +/** @} end of name */ + +/** + * \name PMOD 7 Multiplexor + * @{ + */ +#define PM7_GPIO_D ((0 << BIT0) << PM7_OFFSET) /*!< Pmod7[4:1] are connected to DW GPIO Port D[11:8] */ +#define PM7_STAT ((1 << BIT0) << PM7_OFFSET) /*!< Pmod7[4:1] are connected to the ARC EM sleep status signals */ +/** @} end of name */ +typedef volatile uint32_t MUX_REG; + +#ifdef __cplusplus +extern "C" { +#endif + +extern void mux_init(MUX_REG *mux_regs); +extern MUX_REG *get_mux_regs(void); +extern void set_pmod_mux(MUX_REG *mux_regs, uint32_t val); +extern uint32_t get_pmod_mux(MUX_REG *mux_regs); +extern void change_pmod_mux(MUX_REG *mux_regs, uint32_t val, uint32_t change_bits); +extern void set_spi_map(MUX_REG *mux_regs, uint32_t val); +extern uint32_t get_spi_map(MUX_REG *mux_regs); +extern void set_uart_map(MUX_REG *mux_regs, uint32_t val); +extern uint32_t get_uart_map(MUX_REG *mux_regs); + +#ifdef __cplusplus +} +#endif + +#endif /* _MUX_H_ */ + +/** @} end of group BOARD_EMSK_DRV_MUX */ diff --git a/hw/mcu/arc/src/ext/sdk/board/emsk/common/mux_hal.h b/hw/mcu/arc/src/ext/sdk/board/emsk/common/mux_hal.h new file mode 100644 index 000000000..bee2068bf --- /dev/null +++ b/hw/mcu/arc/src/ext/sdk/board/emsk/common/mux_hal.h @@ -0,0 +1,69 @@ +/* ------------------------------------------ + * Copyright (c) 2016, Synopsys, Inc. All rights reserved. + + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + + * 1) Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + + * 2) 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. + + * 3) Neither the name of the Synopsys, Inc., nor the names of its contributors may + * be used to endorse or promote products derived from this software without + * specific prior written permission. + + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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. + * + * \version 2016.05 + * \date 2014-07-07 + * \author Huaqi Fang(Huaqi.Fang@synopsys.com) +--------------------------------------------- */ + +/** + * \file + * \ingroup BOARD_EMSK_DRV_MUX + * \brief emsk mux control register index header + */ + +/** + * \addtogroup BOARD_EMSK_DRV_MUX + * @{ + */ +#ifndef _MUX_HAL_H_ +#define _MUX_HAL_H_ + +/** + * \name Mux Control Register Index + * @{ + */ +#define PMOD_MUX_CTRL 0 /*!< 32-bits, offset 0x0, + This register controls mapping of the peripheral device signals on Pmod connectors */ + +#define I2C_MAP_CTRL 1 /*!< 32-bits, offset 0x4 */ + +#define SPI_MAP_CTRL 2 /*!< 32-bits, offset 0x8, + SPI_MAP_CTRL[0] selects the mode of operation of the SPI Slave: + - Normal operation, SPI_MAP_CTRL[0]=0: SPI Slave is connected to Pmod1 at connector J1. + - Loop-back mode, SPI_MAP_CTRL[0]=1: SPI Slave is connected to the SPI Master inside the FPGA using CS4. + */ + +#define UART_MAP_CTRL 3 /*!< 32-bits, offset 0x8, + This register controls the mapping of the UART signals on the Pmod1 connector. */ +/** @} end of name */ + + +#endif /* _MUX_HAL_H_ */ + +/** @} end of group BOARD_EMSK_DRV_MUX */ diff --git a/hw/mcu/arc/src/ext/sdk/board/emsk/emsk.h b/hw/mcu/arc/src/ext/sdk/board/emsk/emsk.h new file mode 100644 index 000000000..570408da7 --- /dev/null +++ b/hw/mcu/arc/src/ext/sdk/board/emsk/emsk.h @@ -0,0 +1,128 @@ +/* ------------------------------------------ + * Copyright (c) 2016, Synopsys, Inc. All rights reserved. + + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + + * 1) Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + + * 2) 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. + + * 3) Neither the name of the Synopsys, Inc., nor the names of its contributors may + * be used to endorse or promote products derived from this software without + * specific prior written permission. + + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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. + * + * \version 2016.05 + * \date 2014-06-18 + * \author Wayne Ren(Wei.Ren@synopsys.com) +--------------------------------------------- */ +/** + * + * \file + * \ingroup BOARD_EMSK_COMMON_INIT + * \brief emsk resource definitions + */ + +/** + * \addtogroup BOARD_EMSK_COMMON_INIT + * @{ + */ +#ifndef _EMSK_H_ +#define _EMSK_H_ + +#include "inc/arc/arc_em.h" + +#include "board/emsk/uart/dw_uart_obj.h" +#include "board/emsk/gpio/dw_gpio_obj.h" +#include "board/emsk/gpio/emsk_gpio.h" +#include "board/emsk/iic/dw_iic_obj.h" +#include "board/emsk/spi/dw_spi_obj.h" + +#include "board/emsk/common/emsk_timer.h" + +#include "board/emsk/emsk_hardware.h" + +#define EMSK_GPIO_PORT_A DW_GPIO_PORT_A +#define EMSK_GPIO_PORT_B DW_GPIO_PORT_B +#define EMSK_GPIO_PORT_C DW_GPIO_PORT_C +#define EMSK_GPIO_PORT_D DW_GPIO_PORT_D + +/* common macros must be defined by all boards */ + +#define BOARD_CONSOLE_UART_ID DW_UART_1_ID +#define BOARD_CONSOLE_UART_BAUD UART_BAUDRATE_115200 +#define BOARD_ADC_IIC_ID DW_IIC_0_ID +#define BOARD_TEMP_SENSOR_IIC_ID DW_IIC_0_ID + +#define BOARD_TEMP_IIC_SLVADDR TEMP_I2C_SLAVE_ADDRESS + +#ifndef BOARD_SPI_FREQ +#define BOARD_SPI_FREQ (1000000) +#endif + +#ifndef BOARD_SPI_CLKMODE +#define BOARD_SPI_CLKMODE (SPI_CLK_MODE_0) +#endif + +#define BOARD_SYS_TIMER_ID TIMER_0 +#define BOARD_SYS_TIMER_INTNO INTNO_TIMER0 +#define BOARD_SYS_TIMER_HZ (1000) + +/** board timer count frequency (HZ) */ +#define BOARD_SYS_TIMER_MS_HZ (1000) +/** board timer count frequency convention based on the global timer counter */ +#define BOARD_SYS_TIMER_MS_CONV (BOARD_SYS_TIMER_MS_HZ/BOARD_SYS_TIMER_HZ) + + +#define BOARD_CPU_CLOCK CLK_CPU +#define BOARD_DEV_CLOCK CLK_BUS_APB + +#define BOARD_LED_MASK (0x1ff) +#define BOARD_LED_CNT (9) +#define BOARD_BTN_MASK (0x7) +#define BOARD_BTN_CNT (3) +#define BOARD_SWT_MASK (0xf) +#define BOARD_SWT_CNT (4) + +#define BOARD_ONBOARD_NTSHELL_ID (EMSK_NTSHELL_0_ID) + +#define OSP_DELAY_OS_COMPAT_ENABLE (1) +#define OSP_DELAY_OS_COMPAT_DISABLE (0) + + +#define OSP_GET_CUR_SYSHZ() (gl_emsk_sys_hz_cnt) +#define OSP_GET_CUR_MS() (gl_emsk_ms_cnt) +#define OSP_GET_CUR_US() board_get_cur_us() +#define OSP_GET_CUR_HWTICKS() board_get_hwticks() + +#ifdef __cplusplus +extern "C" { +#endif + +extern void board_init(void); +extern void board_timer_update(uint32_t precision); +extern void board_delay_ms(uint32_t ms, uint8_t os_compat); +extern uint64_t board_get_hwticks(void); +extern uint64_t board_get_cur_us(void); + +#ifdef __cplusplus +} +#endif + +#endif /* _EMSK_H_ */ + +/** @} end of group BOARD_EMSK_COMMON_INIT */ diff --git a/hw/mcu/arc/src/ext/sdk/board/emsk/emsk_hardware.h b/hw/mcu/arc/src/ext/sdk/board/emsk/emsk_hardware.h new file mode 100644 index 000000000..9aecc6cd4 --- /dev/null +++ b/hw/mcu/arc/src/ext/sdk/board/emsk/emsk_hardware.h @@ -0,0 +1,119 @@ +/* ------------------------------------------ + * Copyright (c) 2016, Synopsys, Inc. All rights reserved. + + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + + * 1) Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + + * 2) 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. + + * 3) Neither the name of the Synopsys, Inc., nor the names of its contributors may + * be used to endorse or promote products derived from this software without + * specific prior written permission. + + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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. + * + * \version 2016.05 + * \date 2015-11-16 + * \author Qiang Gu(Qiang.Gu@synopsys.com) +--------------------------------------------- */ +/** + * + * \file + * \ingroup BOARD_EMSK_COMMON_INIT + * \brief emsk hardware resource definitions + */ + +/** + * \addtogroup BOARD_EMSK_COMMON_INIT + * @{ + */ +#ifndef _EMSK_HARDWARE_H_ +#define _EMSK_HARDWARE_H_ + +#include "inc/arc/arc_feature_config.h" + +/** CPU Clock Frequency definition */ +#if defined(BOARD_CPU_FREQ) + /*!< Get cpu clock frequency definition from build system */ + #define CLK_CPU (BOARD_CPU_FREQ) +#elif defined(ARC_FEATURE_CPU_CLOCK_FREQ) + /*!< Get cpu clock frequency definition from tcf file */ + #define CLK_CPU (ARC_FEATURE_CPU_CLOCK_FREQ) +#else + /*!< Default cpu clock frequency */ + #define CLK_CPU (20000000) +#endif + +/** Peripheral Bus Reference Clock definition */ +#ifdef BOARD_DEV_FREQ + /*!< Get peripheral bus reference clock defintion from build system */ + #define CLK_BUS_APB (BOARD_DEV_FREQ) +#else + /*!< Default peripheral bus reference clock defintion */ + #define CLK_BUS_APB (50000000U) +#endif + +/* Device Register Base Address */ +#define REL_REGBASE_PINMUX (0x00000000U) /*!< PINMUX */ +#define REL_REGBASE_SPI_MST_CS_CTRL (0x00000014U) /*!< SPI Master Select Ctrl */ +#define REL_REGBASE_GPIO0 (0x00002000U) /*!< GPIO 0 Onboard */ +#define REL_REGBASE_TIMERS (0x00003000U) /*!< DW TIMER */ +#define REL_REGBASE_I2C0 (0x00004000U) /*!< I2C 0 */ +#define REL_REGBASE_I2C1 (0x00005000U) /*!< I2C 1 */ +#define REL_REGBASE_SPI0 (0x00006000U) /*!< SPI Master */ +#define REL_REGBASE_SPI1 (0x00007000U) /*!< SPI Slave */ +#define REL_REGBASE_UART0 (0x00008000U) /*!< UART0 is connected to PMOD */ +#define REL_REGBASE_UART1 (0x00009000U) /*!< UART1 is USB-UART?? use UART1 as default */ +#define REL_REGBASE_UART2 (0x0000A000U) /*!< UART2 */ +#define REL_REGBASE_WDT (0x0000B000U) /*!< WDT */ +// #define REL_REGBASE_I2S_MASTER_IN (0x0000C000U) /*!< I2S Master In */ +// #define REL_REGBASE_I2S_MASTER_OUT (0x0000D000U) /*!< I2S Master Out */ +// #define REL_REGBASE_GMAC (0x0000E000U) /*!< GMAC */ + +/* Interrupt Connection */ +#define INTNO_TIMER0 16 /*!< ARC Timer0 */ +#define INTNO_TIMER1 17 /*!< ARC Timer1 */ +#define INTNO_SECURE_TIMER0 20 /*!< Core Secure Timer 0 */ +#define INTNO_DMA_START 22 /*!< Core DMA Controller */ +#define INTNO_DMA_COMPLETE 22 /*!< Core DMA Controller Complete */ +#define INTNO_DMA_ERROR 23 /*!< Core DMA Controller Error */ +#define INTNO_GPIO 24 /*!< GPIO controller */ +#define INTNO_I2C0 25 /*!< I2C_0 controller */ +#define INTNO_I2C1 26 /*!< I2C_1 controller */ +#define INTNO_SPI_MASTER 27 /*!< SPI Master controller */ +#define INTNO_SPI_SLAVE 28 /*!< SPI Slave controller */ +#define INTNO_UART0 29 /*!< UART0 */ +#define INTNO_UART1 30 /*!< UART1 */ +#define INTNO_UART2 31 /*!< UART2 */ +#define INTNO_DW_WDT 32 /*!< WDT */ +#define INTNO_DW_TMR0 33 /*!< DW Timer 0 */ +#define INTNO_DW_TMR1 34 /*!< DW Timer 1 */ +// #define INTNO_I2S_Master_In 33 /*!< I2S Master In */ +// #define INTNO_I2S_Master_Out 34 /*!< I2S Master Out */ +// #define INTNO_GMAC 35 /*!< GMAC */ + +/* SPI Mater Signals Usage */ +#define EMSK_SPI_LINE_0 0 /*!< CS0 -- Pmod 6 pin1 */ +#define EMSK_SPI_LINE_1 1 /*!< CS1 -- Pmod 5 pin1 or Pmod 6 pin 7 */ +#define EMSK_SPI_LINE_2 2 /*!< CS2 -- Pmod 6 pin8 */ +#define EMSK_SPI_LINE_SDCARD 3 /*!< CS3 -- On-board SD card */ +#define EMSK_SPI_LINE_SPISLAVE 4 /*!< CS4 -- Internal SPI slave */ +#define EMSK_SPI_LINE_SFLASH 5 /*!< CS5 -- On-board SPI Flash memory */ + +#endif /* _EMSK_HARDWARE_H_ */ + +/** @} end of group BOARD_EMSK_COMMON_INIT */ diff --git a/hw/mcu/arc/src/ext/sdk/board/emsk/gpio/dw_gpio_obj.c b/hw/mcu/arc/src/ext/sdk/board/emsk/gpio/dw_gpio_obj.c new file mode 100644 index 000000000..6e47948df --- /dev/null +++ b/hw/mcu/arc/src/ext/sdk/board/emsk/gpio/dw_gpio_obj.c @@ -0,0 +1,379 @@ +/* ------------------------------------------ + * Copyright (c) 2016, Synopsys, Inc. All rights reserved. + + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + + * 1) Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + + * 2) 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. + + * 3) Neither the name of the Synopsys, Inc., nor the names of its contributors may + * be used to endorse or promote products derived from this software without + * specific prior written permission. + + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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. + * + * \version 2016.05 + * \date 2014-07-24 + * \author Wayne Ren(Wei.Ren@synopsys.com) +--------------------------------------------- */ +/** + * \defgroup BOARD_EMSK_DRV_DW_GPIO_OBJ EMSK DW GPIO Object + * \ingroup BOARD_EMSK_DRIVER + * \brief EMSK Designware GPIO Objects + * \details + * Implement the EMSK board GPIO object using the DesignWare GPIO device driver. + * Only need to implement some DesignWare GPIO structures and combine with EMSK GPIO + * hardware resources, like in C++ class instantiation. + * For example, in C++, define a class called gpio + * class gpio { + * + * }; + * then instantiate the gpio class: + * gpio emsk_gpio_a; + */ + +/** + * \file + * \ingroup BOARD_EMSK_DRV_DW_GPIO_OBJ + * \brief DesignWare GPIO object instantiation on EMSK + */ + +/** + * \addtogroup BOARD_EMSK_DRV_DW_GPIO_OBJ + * @{ + */ +#include "inc/arc/arc.h" +#include "inc/arc/arc_builtin.h" + +#include "board/emsk/gpio/dw_gpio_obj.h" + +#include "board/emsk/emsk.h" +/* + * Uncomment this to enable default + * gpio bit handler output message + * by uart + */ + +#ifdef ARC_FEATURE_DMP_PERIPHERAL +#define PERIPHERAL_BASE ARC_FEATURE_DMP_PERIPHERAL +#else +#define PERIPHERAL_BASE _arc_aux_read(AUX_DMP_PERIPHERAL) +#endif + +#if (USE_DW_GPIO_PORT_A) +static DEV_GPIO port_a; +static DW_GPIO_PORT dw_gpio_port_a; +static DEV_GPIO_HANDLER dw_gpio_bit_handler_a[EMSK_GPIO_A_INT_MAX_COUNT]; +static DW_GPIO_BIT_ISR dw_gpio_bit_isr_a = { + EMSK_GPIO_A_INT_MAX_COUNT, dw_gpio_bit_handler_a +}; + +static int32_t porta_open(uint32_t dir) +{ + return dw_gpio_open(&port_a, dir); +} + +static int32_t porta_close(void) +{ + return dw_gpio_close(&port_a); +} + +static int32_t porta_control(uint32_t ctrl_cmd, void *param) +{ + return dw_gpio_control(&port_a, ctrl_cmd, param); +} + +static int32_t porta_write(uint32_t val, uint32_t mask) +{ + return dw_gpio_write(&port_a, val, mask); +} + +static int32_t porta_read(uint32_t *val, uint32_t mask) +{ + return dw_gpio_read(&port_a, val, mask); +} + +static void porta_isr(void *ptr) +{ + dw_gpio_isr_handler(&port_a, ptr); +} + +static void porta_install(void) +{ + uint32_t i; + DEV_GPIO_PTR port_ptr = &port_a; + DEV_GPIO_INFO_PTR info_ptr = &(port_a.gpio_info); + DW_GPIO_PORT_PTR dw_port_ptr = &(dw_gpio_port_a); + + info_ptr->gpio_ctrl = (void *)dw_port_ptr; + info_ptr->opn_cnt = 0; + info_ptr->method = 0; + info_ptr->direction = 0; + info_ptr->extra = 0; + + dw_port_ptr->no = DW_GPIO_PORT_A; + dw_port_ptr->regs = (DW_GPIO_REG_PTR)(PERIPHERAL_BASE|REL_REGBASE_GPIO0); + dw_port_ptr->valid_bit_mask = EMSK_GPIO_A_VALID_MASK; + dw_port_ptr->intno = INTNO_GPIO; + dw_port_ptr->int_handler = porta_isr; + + for (i=0; igpio_bit_isr = &dw_gpio_bit_isr_a; + + port_ptr->gpio_open = porta_open; + port_ptr->gpio_close = porta_close; + port_ptr->gpio_control = porta_control; + port_ptr->gpio_write = porta_write; + port_ptr->gpio_read = porta_read; +} +#endif + +#if (USE_DW_GPIO_PORT_B) +static DEV_GPIO port_b; +static DW_GPIO_PORT dw_gpio_port_b; + +static int32_t portb_open(uint32_t dir) +{ + return dw_gpio_open(&port_b, dir); +} + +static int32_t portb_close(void) +{ + return dw_gpio_close(&port_b); +} + +static int32_t portb_control(uint32_t ctrl_cmd, void *param) +{ + return dw_gpio_control(&port_b, ctrl_cmd, param); +} + +static int32_t portb_write(uint32_t val, uint32_t mask) +{ + return dw_gpio_write(&port_b, val, mask); +} + +static int32_t portb_read(uint32_t *val, uint32_t mask) +{ + return dw_gpio_read(&port_b, val, mask); +} + +static void portb_isr(void *ptr) +{ + dw_gpio_isr_handler(&port_b, ptr); +} + +static void portb_install(void) +{ + DEV_GPIO_PTR port_ptr = &port_b; + DEV_GPIO_INFO_PTR info_ptr = &(port_b.gpio_info); + DW_GPIO_PORT_PTR dw_port_ptr = &(dw_gpio_port_b); + + info_ptr->gpio_ctrl = (void *)dw_port_ptr; + info_ptr->opn_cnt = 0; + info_ptr->method = 0; + info_ptr->direction = 0; + info_ptr->extra = 0; + + dw_port_ptr->no = DW_GPIO_PORT_B; + dw_port_ptr->regs = (DW_GPIO_REG_PTR)(PERIPHERAL_BASE|REL_REGBASE_GPIO0); + dw_port_ptr->valid_bit_mask = EMSK_GPIO_B_VALID_MASK; + + dw_port_ptr->intno = INTNO_GPIO; + dw_port_ptr->int_handler = portb_isr; + dw_port_ptr->gpio_bit_isr = NULL; + + port_ptr->gpio_open = portb_open; + port_ptr->gpio_close = portb_close; + port_ptr->gpio_control = portb_control; + port_ptr->gpio_write = portb_write; + port_ptr->gpio_read = portb_read; +} +#endif + + +#if (USE_DW_GPIO_PORT_C) +static DEV_GPIO port_c; +static DW_GPIO_PORT dw_gpio_port_c; + +static int32_t portc_open(uint32_t dir) +{ + return dw_gpio_open(&port_c, dir); +} + +static int32_t portc_close(void) +{ + return dw_gpio_close(&port_c); +} + +static int32_t portc_control(uint32_t ctrl_cmd, void *param) +{ + return dw_gpio_control(&port_c, ctrl_cmd, param); +} + +static int32_t portc_write(uint32_t val, uint32_t mask) +{ + return dw_gpio_write(&port_c, val, mask); +} + +static int32_t portc_read(uint32_t *val, uint32_t mask) +{ + return dw_gpio_read(&port_c, val, mask); +} + +static void portc_isr(void *ptr) +{ + dw_gpio_isr_handler(&port_c, ptr); +} + +static void portc_install(void) +{ + DEV_GPIO_PTR port_ptr = &port_c; + DEV_GPIO_INFO_PTR info_ptr = &(port_c.gpio_info); + DW_GPIO_PORT_PTR dw_port_ptr = &(dw_gpio_port_c); + + info_ptr->gpio_ctrl = (void *)dw_port_ptr; + info_ptr->opn_cnt = 0; + info_ptr->method = 0; + info_ptr->direction = 0; + info_ptr->extra = 0; + + dw_port_ptr->no = DW_GPIO_PORT_C; + dw_port_ptr->regs = (DW_GPIO_REG_PTR)(PERIPHERAL_BASE|REL_REGBASE_GPIO0); + dw_port_ptr->valid_bit_mask = EMSK_GPIO_C_VALID_MASK; + + dw_port_ptr->intno = INTNO_GPIO; + dw_port_ptr->int_handler = portc_isr; + dw_port_ptr->gpio_bit_isr = NULL; + + port_ptr->gpio_open = portc_open; + port_ptr->gpio_close = portc_close; + port_ptr->gpio_control = portc_control; + port_ptr->gpio_write = portc_write; + port_ptr->gpio_read = portc_read; +} +#endif + +#if (USE_DW_GPIO_PORT_D) +static DEV_GPIO port_d; +static DW_GPIO_PORT dw_gpio_port_d; + +static int32_t portd_open(uint32_t dir) +{ + return dw_gpio_open(&port_d, dir); +} + +static int32_t portd_close(void) +{ + return dw_gpio_close(&port_d); +} + +static int32_t portd_control(uint32_t ctrl_cmd, void *param) +{ + return dw_gpio_control(&port_d, ctrl_cmd, param); +} + +static int32_t portd_write(uint32_t val, uint32_t mask) +{ + return dw_gpio_write(&port_d, val, mask); +} + +static int32_t portd_read(uint32_t *val, uint32_t mask) +{ + return dw_gpio_read(&port_d, val, mask); +} + +static void portd_isr(void *ptr) +{ + dw_gpio_isr_handler(&port_d, ptr); +} + +static void portd_install(void) +{ + DEV_GPIO_PTR port_ptr = &port_d; + DEV_GPIO_INFO_PTR info_ptr = &(port_d.gpio_info); + DW_GPIO_PORT_PTR dw_port_ptr = &(dw_gpio_port_d); + + info_ptr->gpio_ctrl = (void *)dw_port_ptr; + info_ptr->opn_cnt = 0; + info_ptr->method = 0; + info_ptr->direction = 0; + info_ptr->extra = 0; + + dw_port_ptr->no = DW_GPIO_PORT_D; + dw_port_ptr->regs = (DW_GPIO_REG_PTR)(PERIPHERAL_BASE|REL_REGBASE_GPIO0); + dw_port_ptr->valid_bit_mask = EMSK_GPIO_D_VALID_MASK; + + dw_port_ptr->intno = INTNO_GPIO; + dw_port_ptr->int_handler = portd_isr; + dw_port_ptr->gpio_bit_isr = NULL; + + port_ptr->gpio_open = portd_open; + port_ptr->gpio_close = portd_close; + port_ptr->gpio_control = portd_control; + port_ptr->gpio_write = portd_write; + port_ptr->gpio_read = portd_read; +} +#endif + +DEV_GPIO_PTR gpio_get_dev(int32_t gpio_id) +{ + static uint32_t install_flag = 0; + + /* intall device objects */ + if (install_flag == 0) { + install_flag = 1; + dw_gpio_all_install(); + } + + switch (gpio_id) { +#if (USE_DW_GPIO_PORT_A) + case DW_GPIO_PORT_A: return &port_a; +#endif +#if (USE_DW_GPIO_PORT_B) + case DW_GPIO_PORT_B: return &port_b; +#endif +#if (USE_DW_GPIO_PORT_C) + case DW_GPIO_PORT_C: return &port_c; +#endif +#if (USE_DW_GPIO_PORT_D) + case DW_GPIO_PORT_D: return &port_d; +#endif + default: + break; + } + return NULL; +} + +void dw_gpio_all_install(void) +{ +#if (USE_DW_GPIO_PORT_A) + porta_install(); +#endif +#if (USE_DW_GPIO_PORT_B) + portb_install(); +#endif +#if (USE_DW_GPIO_PORT_C) + portc_install(); +#endif +#if (USE_DW_GPIO_PORT_D) + portd_install(); +#endif +} + +/** @} end of group BOARD_EMSK_DRV_DW_GPIO_OBJ */ diff --git a/hw/mcu/arc/src/ext/sdk/board/emsk/gpio/dw_gpio_obj.h b/hw/mcu/arc/src/ext/sdk/board/emsk/gpio/dw_gpio_obj.h new file mode 100644 index 000000000..67ddac572 --- /dev/null +++ b/hw/mcu/arc/src/ext/sdk/board/emsk/gpio/dw_gpio_obj.h @@ -0,0 +1,90 @@ +/* ------------------------------------------ + * Copyright (c) 2016, Synopsys, Inc. All rights reserved. + + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + + * 1) Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + + * 2) 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. + + * 3) Neither the name of the Synopsys, Inc., nor the names of its contributors may + * be used to endorse or promote products derived from this software without + * specific prior written permission. + + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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. + * + * \version 2016.05 + * \date 2014-07-24 + * \author Wayne Ren(Wei.Ren@synopsys.com) +--------------------------------------------- */ +/** + * \file + * \ingroup BOARD_EMSK_DRV_DW_GPIO_OBJ + * \brief header file of designware gpio object instantiation on emsk + */ + +/** + * \addtogroup BOARD_EMSK_DRV_DW_GPIO_OBJ + * @{ + */ +#ifndef _DW_GPIO_OBJ_H_ +#define _DW_GPIO_OBJ_H_ + +#include "device/designware/gpio/dw_gpio.h" + +/** + * \name Designware GPIO Port Bank Control Macros + * @{ + */ +#define USE_DW_GPIO_PORT_A 1 +#define USE_DW_GPIO_PORT_B 1 +#define USE_DW_GPIO_PORT_C 1 +#define USE_DW_GPIO_PORT_D 1 +/** @} end of name */ + +/** + * \name Designware GPIO Port Interrupt Available Number Macros + * @{ + */ +#define EMSK_GPIO_A_INT_MAX_COUNT 32 +#define EMSK_GPIO_B_INT_MAX_COUNT 0 +#define EMSK_GPIO_C_INT_MAX_COUNT 0 +#define EMSK_GPIO_D_INT_MAX_COUNT 0 +/** @} end of name */ + +/** + * \name Designware GPIO Port Available Bits Macros + * @{ + */ +#define EMSK_GPIO_A_VALID_MASK DW_GPIO_MASK_ALL +#define EMSK_GPIO_B_VALID_MASK DW_GPIO_MASK_ALL +#define EMSK_GPIO_C_VALID_MASK DW_GPIO_MASK_ALL +#define EMSK_GPIO_D_VALID_MASK DW_GPIO_MASK_ALL +/** @} end of name */ + +#ifdef __cplusplus +extern "C" { +#endif + +extern void dw_gpio_all_install(void); + +#ifdef __cplusplus +} +#endif + +#endif /* _DW_GPIO_OBJ_H_*/ + +/** @} end of group BOARD_EMSK_DRV_DW_GPIO_OBJ */ diff --git a/hw/mcu/arc/src/ext/sdk/board/emsk/gpio/emsk_gpio.c b/hw/mcu/arc/src/ext/sdk/board/emsk/gpio/emsk_gpio.c new file mode 100644 index 000000000..fae676c49 --- /dev/null +++ b/hw/mcu/arc/src/ext/sdk/board/emsk/gpio/emsk_gpio.c @@ -0,0 +1,199 @@ +/* ------------------------------------------ + * Copyright (c) 2016, Synopsys, Inc. All rights reserved. + + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + + * 1) Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + + * 2) 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. + + * 3) Neither the name of the Synopsys, Inc., nor the names of its contributors may + * be used to endorse or promote products derived from this software without + * specific prior written permission. + + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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. + * + * \version 2016.05 + * \date 2014-07-31 + * \author Wayne Ren(Wei.Ren@synopsys.com) +--------------------------------------------- */ +/** + * \defgroup BOARD_EMSK_DRV_GPIO EMSK GPIO Driver + * \ingroup BOARD_EMSK_DRIVER + * \brief EMSK Onboard GPIO Peripherals Driver + * \details + * Implementation of EMSK on-board button, led, dip switch driver, + * this is for better use, you don't have to get a gpio object before operating + * led,button,switch, because some basic functions for usage are provided. + */ + +/** + * \file + * \ingroup BOARD_EMSK_DRV_GPIO + * \brief all on emsk board gpio device init and operate functions + * \details this gpio devices are button, led, dip switch + */ + +/** + * \addtogroup BOARD_EMSK_DRV_GPIO + * @{ + */ +#include "inc/arc/arc.h" +#include "inc/arc/arc_builtin.h" +#include "inc/embARC_toolchain.h" +#include "inc/embARC_error.h" + +#include "board/emsk/gpio/emsk_gpio.h" +#include "board/emsk/emsk.h" + +static DEV_GPIO *led_port; +static DEV_GPIO *button_port; +static DEV_GPIO *switch_port; + +#define EMSK_GPIO_CHECK_EXP_NORTN(EXPR) CHECK_EXP_NOERCD(EXPR, error_exit) + +/** emsk on board gpio init */ +void emsk_gpio_init(void) +{ + emsk_led_init(); + emsk_button_init(); + emsk_switch_init(); +} + +/** emsk on-board led init, led default off */ +void emsk_led_init(void) +{ + led_port = gpio_get_dev(EMSK_LED_PORT); + + EMSK_GPIO_CHECK_EXP_NORTN(led_port != NULL); + + if (led_port->gpio_open(EMSK_LED_DIR) == E_OPNED) { + led_port->gpio_control(GPIO_CMD_SET_BIT_DIR_OUTPUT, (void *)(EMSK_LED_MASK)); + led_port->gpio_control(GPIO_CMD_DIS_BIT_INT, (void *)(EMSK_LED_MASK)); + } + + led_write(0, BOARD_LED_MASK); + +error_exit: + return; +} + +/** emsk on-board button init */ +void emsk_button_init(void) +{ + button_port = gpio_get_dev(EMSK_BUTTON_PORT); + + EMSK_GPIO_CHECK_EXP_NORTN(button_port != NULL); + + if (button_port->gpio_open(EMSK_BUTTON_DIR) == E_OPNED) { + button_port->gpio_control(GPIO_CMD_SET_BIT_DIR_INPUT, (void *)(EMSK_BUTTON_MASK)); + button_port->gpio_control(GPIO_CMD_DIS_BIT_INT, (void *)(EMSK_BUTTON_MASK)); + } + +error_exit: + return; +} + +/** emsk on-board switch init */ +void emsk_switch_init(void) +{ + switch_port = gpio_get_dev(EMSK_SWITCH_PORT); + + EMSK_GPIO_CHECK_EXP_NORTN(switch_port != NULL); + + if (switch_port->gpio_open(EMSK_SWITCH_DIR) == E_OPNED) { + switch_port->gpio_control(GPIO_CMD_SET_BIT_DIR_INPUT, (void *)(EMSK_SWITCH_MASK)); + switch_port->gpio_control(GPIO_CMD_DIS_BIT_INT, (void *)(EMSK_SWITCH_MASK)); + } + +error_exit: + return; +} + +/** + * workaround for get led value + * because gpio read return is not right + */ +static uint32_t g_led_val; +/** write 1 to light on led bit, else light off led */ +void led_write(uint32_t led_val, uint32_t mask) +{ + EMSK_GPIO_CHECK_EXP_NORTN(led_port != NULL); + + led_val = (~led_val) & mask; + led_val = led_val << EMSK_LED_OFFSET; + mask = (mask << EMSK_LED_OFFSET) & EMSK_LED_MASK; + led_port->gpio_write(led_val, mask); + + g_led_val = led_val; + +error_exit: + return; +} + +/** read led value, on for 1, off for 0 */ +/** \todo need to find why when led set to output then can't get the right value of led */ +uint32_t led_read(uint32_t mask) +{ + uint32_t value; + + EMSK_GPIO_CHECK_EXP_NORTN(led_port != NULL); + + mask = (mask << EMSK_LED_OFFSET) & EMSK_LED_MASK; + led_port->gpio_read(&value, mask); + value = (~value) & EMSK_LED_MASK; + + return (value >> EMSK_LED_OFFSET); + +error_exit: + return 0; +} + +/** Pull down switch return 1, else 0 */ +uint32_t switch_read(uint32_t mask) +{ + uint32_t value; + + EMSK_GPIO_CHECK_EXP_NORTN(switch_port != NULL); + + mask = (mask << EMSK_SWITCH_OFFSET) & EMSK_SWITCH_MASK; + switch_port->gpio_read(&value, mask); + value = (~value) & mask; + + return (value >> EMSK_SWITCH_OFFSET); + +error_exit: + return 0; +} + +/** Press down bit set to 1 else 0 */ +uint32_t button_read(uint32_t mask) +{ + uint32_t value; + + EMSK_GPIO_CHECK_EXP_NORTN(button_port != NULL); + + mask = (mask << EMSK_BUTTON_OFFSET) & EMSK_BUTTON_MASK; + button_port->gpio_read(&value, mask); + value = (~value) & mask; + + return (value >> EMSK_BUTTON_OFFSET); + +error_exit: + return 0; +} + +/** @} end of group BOARD_EMSK_DRV_GPIO */ diff --git a/hw/mcu/arc/src/ext/sdk/board/emsk/gpio/emsk_gpio.h b/hw/mcu/arc/src/ext/sdk/board/emsk/gpio/emsk_gpio.h new file mode 100644 index 000000000..7d2ee714d --- /dev/null +++ b/hw/mcu/arc/src/ext/sdk/board/emsk/gpio/emsk_gpio.h @@ -0,0 +1,96 @@ +/* ------------------------------------------ + * Copyright (c) 2016, Synopsys, Inc. All rights reserved. + + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + + * 1) Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + + * 2) 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. + + * 3) Neither the name of the Synopsys, Inc., nor the names of its contributors may + * be used to endorse or promote products derived from this software without + * specific prior written permission. + + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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. + * + * \version 2016.05 + * \date 2014-07-31 + * \author Wayne Ren(Wei.Ren@synopsys.com) +--------------------------------------------- */ +/** + * \file + * \ingroup BOARD_EMSK_DRV_GPIO + * \brief emsk board gpio related functions header + */ +/** + * \addtogroup BOARD_EMSK_DRV_GPIO + * @{ + */ +#ifndef _EMSK_GPIO_H_ +#define _EMSK_GPIO_H_ + +#include "device/designware/gpio/dw_gpio.h" + +/** + * \name EMSK LED Port Configuration + * @{ + */ +#define EMSK_LED_OFFSET (0) +#define EMSK_LED_MASK ((0x1ff) << EMSK_LED_OFFSET) +#define EMSK_LED_PORT (DW_GPIO_PORT_B) +#define EMSK_LED_DIR ((0x1ff) << EMSK_LED_OFFSET) +/** @} end of name */ + +/** + * \name EMSK Switch Port Configuration + * @{ + */ +#define EMSK_SWITCH_OFFSET (0) +#define EMSK_SWITCH_MASK ((0xf) << EMSK_SWITCH_OFFSET) +#define EMSK_SWITCH_PORT (DW_GPIO_PORT_C) +#define EMSK_SWITCH_DIR ((0x0) << EMSK_SWITCH_OFFSET) +/** @} end of name */ + +/** + * \name EMSK Button Port Configuration + * @{ + */ +#define EMSK_BUTTON_OFFSET (0) +#define EMSK_BUTTON_MASK ((0x7) << EMSK_BUTTON_OFFSET) +#define EMSK_BUTTON_PORT (DW_GPIO_PORT_A) +#define EMSK_BUTTON_DIR ((0x0) << EMSK_BUTTON_OFFSET) +/** @} end of name */ + +#ifdef __cplusplus +extern "C" { +#endif + +extern void emsk_led_init(void); +extern void emsk_button_init(void); +extern void emsk_switch_init(void); +extern void emsk_gpio_init(void); +extern void led_write(uint32_t led_val, uint32_t mask); +extern uint32_t led_read(uint32_t mask); +extern uint32_t switch_read(uint32_t mask); +extern uint32_t button_read(uint32_t mask); + +#ifdef __cplusplus +} +#endif + +#endif /* _EMSK_GPIO_H_ */ + +/** @} end of group BOARD_EMSK_DRV_GPIO */ diff --git a/hw/mcu/arc/src/ext/sdk/board/emsk/iic/dw_iic_obj.c b/hw/mcu/arc/src/ext/sdk/board/emsk/iic/dw_iic_obj.c new file mode 100644 index 000000000..f1c3a2a61 --- /dev/null +++ b/hw/mcu/arc/src/ext/sdk/board/emsk/iic/dw_iic_obj.c @@ -0,0 +1,302 @@ +/* ------------------------------------------ + * Copyright (c) 2017, Synopsys, Inc. All rights reserved. + + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + + * 1) Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + + * 2) 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. + + * 3) Neither the name of the Synopsys, Inc., nor the names of its contributors may + * be used to endorse or promote products derived from this software without + * specific prior written permission. + + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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. + * + * \version 2017.03 + * \date 2014-07-03 + * \author Huaqi Fang(Huaqi.Fang@synopsys.com) +--------------------------------------------- */ + +/** + * \defgroup BOARD_EMSK_DRV_DW_IIC_OBJ EMSK DW IIC Object + * \ingroup BOARD_EMSK_DRIVER + * \brief EMSK Designware IIC Objects + * \details + * Realize the EMSK board iic object using designware iic device driver, + * only need to realize some designware iic structures combine with EMSK iic + * hardware resource. just like cpp class instantiation. + */ + +/** + * \file + * \ingroup BOARD_EMSK_DRV_DW_IIC_OBJ + * \brief designware iic object instantiation on emsk + */ + +/** + * \addtogroup BOARD_EMSK_DRV_DW_IIC_OBJ + * @{ + */ +#include "inc/arc/arc.h" +#include "inc/arc/arc_builtin.h" +#include "inc/embARC_toolchain.h" +#include "inc/embARC_error.h" + +#include "inc/arc/arc_exception.h" + +#include "device/designware/iic/dw_iic.h" +#include "board/emsk/iic/dw_iic_obj.h" + +#include "board/emsk/emsk.h" + +#ifdef ARC_FEATURE_DMP_PERIPHERAL +#define PERIPHERAL_BASE ARC_FEATURE_DMP_PERIPHERAL +#else +#define PERIPHERAL_BASE _arc_aux_read(AUX_DMP_PERIPHERAL) +#endif + +/** + * \name EMSK DesignWare IIC 0 Object Instantiation + * @{ + */ +#if (USE_DW_IIC_0) +static void dw_iic_0_isr(void *ptr); +#define DW_IIC_0_RELBASE (REL_REGBASE_I2C0) /*!< designware iic 0 relative baseaddr */ +#define DW_IIC_0_INTNO (INTNO_I2C0) /*!< designware iic 0 interrupt number */ +#define DW_IIC_0_SLVADDR (0x55) /*!< iic 0 slave address working in slave mode */ +#define DW_IIC_0_TX_FIFO_LEN (32) +#define DW_IIC_0_RX_FIFO_LEN (32) +#define DW_IIC_0_MASTER_CODE (0) +#define DW_IIC_0_TARADDR (0x55) + +DEV_IIC dw_iic_0; /*!< designware iic object */ +DW_IIC_CTRL dw_iic_0_ctrl; /*!< designware iic 0 ctrl */ + +/** designware iic 0 open */ +static int32_t dw_iic_0_open (uint32_t mode, uint32_t param) +{ + return dw_iic_open(&dw_iic_0, mode, param); +} +/** designware iic 0 close */ +static int32_t dw_iic_0_close (void) +{ + return dw_iic_close(&dw_iic_0); +} +/** designware iic 0 control */ +static int32_t dw_iic_0_control (uint32_t ctrl_cmd, void *param) +{ + return dw_iic_control(&dw_iic_0, ctrl_cmd, param); +} +/** designware iic 0 write */ +static int32_t dw_iic_0_write (const void *data, uint32_t len) +{ + return dw_iic_write(&dw_iic_0, data, len); +} +/** designware iic 0 close */ +static int32_t dw_iic_0_read (void *data, uint32_t len) +{ + return dw_iic_read(&dw_iic_0, data, len); +} +/** designware iic 0 interrupt routine */ +static void dw_iic_0_isr(void *ptr) +{ + dw_iic_isr(&dw_iic_0, ptr); +} +/** install designware iic 0 to system */ +static void dw_iic_0_install(void) +{ + uint32_t iic_abs_base = 0; + DEV_IIC *dw_iic_ptr = &dw_iic_0; + DEV_IIC_INFO *dw_iic_info_ptr = &(dw_iic_0.iic_info); + DW_IIC_CTRL *dw_iic_ctrl_ptr = &dw_iic_0_ctrl; + DW_IIC_REG *dw_iic_reg_ptr; + + /* Info init */ + dw_iic_info_ptr->iic_ctrl = (void *)dw_iic_ctrl_ptr; + dw_iic_info_ptr->opn_cnt = 0; + dw_iic_info_ptr->addr_mode = IIC_7BIT_ADDRESS; + dw_iic_info_ptr->tar_addr = DW_IIC_0_TARADDR; + /* + * get absolute designware base address + */ + iic_abs_base = (uint32_t)PERIPHERAL_BASE + DW_IIC_0_RELBASE; + dw_iic_reg_ptr = (DW_IIC_REG *)iic_abs_base; + + /* iic ctrl init */ + dw_iic_ctrl_ptr->dw_iic_regs = dw_iic_reg_ptr; + /* Variables which should be set during object implementation */ + dw_iic_ctrl_ptr->support_modes = DW_IIC_BOTH_SUPPORTED; + dw_iic_ctrl_ptr->tx_fifo_len = DW_IIC_0_TX_FIFO_LEN; + dw_iic_ctrl_ptr->rx_fifo_len = DW_IIC_0_RX_FIFO_LEN; + dw_iic_ctrl_ptr->iic_master_code = DW_IIC_0_MASTER_CODE; + dw_iic_ctrl_ptr->retry_cnt = DW_IIC_MAX_RETRY_COUNT; + dw_iic_ctrl_ptr->intno = DW_IIC_0_INTNO; + dw_iic_ctrl_ptr->dw_iic_int_handler = dw_iic_0_isr; + dw_iic_ctrl_ptr->iic_spklen = dw_iic_spklen_const; + dw_iic_ctrl_ptr->iic_scl_cnt = dw_iic_sclcnt_const; + /* Variables which always change during iic operation */ + dw_iic_ctrl_ptr->int_status = 0; + dw_iic_ctrl_ptr->iic_tx_over = 0; + dw_iic_ctrl_ptr->iic_rx_over = 0; + + /** iic dev init */ + dw_iic_ptr->iic_open = dw_iic_0_open; + dw_iic_ptr->iic_close = dw_iic_0_close; + dw_iic_ptr->iic_control = dw_iic_0_control; + dw_iic_ptr->iic_write = dw_iic_0_write; + dw_iic_ptr->iic_read = dw_iic_0_read; +} +#endif /* USE_DW_IIC_0 */ +/** @} end of name */ + +/** + * \name EMSK DesignWare IIC 1 Object Instantiation + * @{ + */ +#if (USE_DW_IIC_1) +static void dw_iic_1_isr(void *ptr); +#define DW_IIC_1_RELBASE (REL_REGBASE_I2C1) /*!< designware iic 1 relative baseaddr */ +#define DW_IIC_1_INTNO (INTNO_I2C1) /*!< designware iic 1 interrupt number */ +#define DW_IIC_1_SLVADDR (0x56) /*!< iic 1 slave address working in slave mode */ +#define DW_IIC_1_TX_FIFO_LEN (32) +#define DW_IIC_1_RX_FIFO_LEN (32) +#define DW_IIC_1_MASTER_CODE (1) +#define DW_IIC_1_TARADDR (0x56) + +DEV_IIC dw_iic_1; /*!< designware iic 1 object */ +DW_IIC_CTRL dw_iic_1_ctrl; /*!< designware iic 1 ctrl */ + +/** designware iic 1 open */ +static int32_t dw_iic_1_open (uint32_t mode, uint32_t param) +{ + return dw_iic_open(&dw_iic_1, mode, param); +} +/** designware iic 1 close */ +static int32_t dw_iic_1_close (void) +{ + return dw_iic_close(&dw_iic_1); +} +/** designware iic 1 control */ +static int32_t dw_iic_1_control (uint32_t ctrl_cmd, void *param) +{ + return dw_iic_control(&dw_iic_1, ctrl_cmd, param); +} +/** designware iic 1 write */ +static int32_t dw_iic_1_write (const void *data, uint32_t len) +{ + return dw_iic_write(&dw_iic_1, data, len); +} +/** designware iic 1 close */ +static int32_t dw_iic_1_read (void *data, uint32_t len) +{ + return dw_iic_read(&dw_iic_1, data, len); +} +/** designware iic 1 interrupt routine */ +static void dw_iic_1_isr(void *ptr) +{ + dw_iic_isr(&dw_iic_1, ptr); +} +/** install designware iic 1 to system */ +static void dw_iic_1_install(void) +{ + uint32_t iic_abs_base = 0; + DEV_IIC *dw_iic_ptr = &dw_iic_1; + DEV_IIC_INFO *dw_iic_info_ptr = &(dw_iic_1.iic_info); + DW_IIC_CTRL *dw_iic_ctrl_ptr = &dw_iic_1_ctrl; + DW_IIC_REG *dw_iic_reg_ptr; + + /* Info init */ + dw_iic_info_ptr->iic_ctrl = (void *)dw_iic_ctrl_ptr; + dw_iic_info_ptr->opn_cnt = 0; + dw_iic_info_ptr->addr_mode = IIC_7BIT_ADDRESS; + dw_iic_info_ptr->tar_addr = DW_IIC_1_TARADDR; + /* + * get absolute designware base address + */ + iic_abs_base = (uint32_t)PERIPHERAL_BASE + DW_IIC_1_RELBASE; + dw_iic_reg_ptr = (DW_IIC_REG *)iic_abs_base; + + /* iic ctrl init */ + dw_iic_ctrl_ptr->dw_iic_regs = dw_iic_reg_ptr; + /* Variables which should be set during object implementation */ + dw_iic_ctrl_ptr->support_modes = DW_IIC_BOTH_SUPPORTED; + dw_iic_ctrl_ptr->tx_fifo_len = DW_IIC_1_TX_FIFO_LEN; + dw_iic_ctrl_ptr->rx_fifo_len = DW_IIC_1_RX_FIFO_LEN; + dw_iic_ctrl_ptr->iic_master_code = DW_IIC_1_MASTER_CODE; + dw_iic_ctrl_ptr->retry_cnt = DW_IIC_MAX_RETRY_COUNT; + dw_iic_ctrl_ptr->intno = DW_IIC_1_INTNO; + dw_iic_ctrl_ptr->dw_iic_int_handler = dw_iic_1_isr; + dw_iic_ctrl_ptr->iic_spklen = dw_iic_spklen_const; + dw_iic_ctrl_ptr->iic_scl_cnt = dw_iic_sclcnt_const; + /* Variables which always change during iic operation */ + dw_iic_ctrl_ptr->int_status = 0; + dw_iic_ctrl_ptr->iic_tx_over = 0; + dw_iic_ctrl_ptr->iic_rx_over = 0; + + /** iic dev init */ + dw_iic_ptr->iic_open = dw_iic_1_open; + dw_iic_ptr->iic_close = dw_iic_1_close; + dw_iic_ptr->iic_control = dw_iic_1_control; + dw_iic_ptr->iic_write = dw_iic_1_write; + dw_iic_ptr->iic_read = dw_iic_1_read; +} +#endif /* USE_DW_IIC_1 */ +/** @} end of name */ + +/** get one designware device structure */ +DEV_IIC_PTR iic_get_dev(int32_t iic_id) +{ + static uint32_t install_flag = 0; + + /* intall device objects */ + if (install_flag == 0) { + install_flag = 1; + dw_iic_all_install(); + } + + switch (iic_id) { +#if (USE_DW_IIC_0) + case DW_IIC_0_ID: + return &dw_iic_0; + break; +#endif +#if (USE_DW_IIC_1) + case DW_IIC_1_ID: + return &dw_iic_1; + break; +#endif + default: + break; + } + return NULL; +} + +/** + * \brief install all iic objects + * \note \b MUST be called during system init + */ +void dw_iic_all_install(void) +{ +#if (USE_DW_IIC_0) + dw_iic_0_install(); +#endif +#if (USE_DW_IIC_1) + dw_iic_1_install(); +#endif +} + +/** @} end of group BOARD_EMSK_DRV_DW_IIC_OBJ */ diff --git a/hw/mcu/arc/src/ext/sdk/board/emsk/iic/dw_iic_obj.h b/hw/mcu/arc/src/ext/sdk/board/emsk/iic/dw_iic_obj.h new file mode 100644 index 000000000..7671889fe --- /dev/null +++ b/hw/mcu/arc/src/ext/sdk/board/emsk/iic/dw_iic_obj.h @@ -0,0 +1,83 @@ +/* ------------------------------------------ + * Copyright (c) 2017, Synopsys, Inc. All rights reserved. + + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + + * 1) Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + + * 2) 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. + + * 3) Neither the name of the Synopsys, Inc., nor the names of its contributors may + * be used to endorse or promote products derived from this software without + * specific prior written permission. + + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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. + * + * \version 2017.03 + * \date 2014-07-03 + * \author Huaqi Fang(Huaqi.Fang@synopsys.com) +--------------------------------------------- */ +/** + * \file + * \ingroup BOARD_EMSK_DRV_DW_IIC_OBJ + * \brief header file of designware iic object instantiation on emsk + */ + +/** + * \addtogroup BOARD_EMSK_DRV_DW_IIC_OBJ + * @{ + */ +#ifndef _DW_IIC_OBJ_H_ +#define _DW_IIC_OBJ_H_ + +#include "device/device_hal/inc/dev_iic.h" + +/** + * \name DesignWare IIC Object Number + * @{ + */ +#define DW_IIC_NUM (1) /*!< DesignWare IIC valid number */ +/** @} end of name */ + +/** + * \name Designware IIC Object ID Macros + * @{ + */ +#define DW_IIC_0_ID 0 /*!< iic 0 id macro */ +#define DW_IIC_1_ID 1 /*!< iic 1 id macro */ +/** @} end of name */ + +/** + * \name Designware IIC Object Control Macros + * @{ + */ +#define USE_DW_IIC_0 1 /*!< enable use designware iic 0 */ +#define USE_DW_IIC_1 1 /*!< enable use designware iic 1 */ +/** @} end of name */ + +#ifdef __cplusplus +extern "C" { +#endif + +extern void dw_iic_all_install(void); + +#ifdef __cplusplus +} +#endif + +#endif /* _DW_IIC_OBJ_H_ */ + +/** @} end of group BOARD_EMSK_IIC_OBJ */ diff --git a/hw/mcu/arc/src/ext/sdk/board/emsk/spi/dw_spi_obj.c b/hw/mcu/arc/src/ext/sdk/board/emsk/spi/dw_spi_obj.c new file mode 100644 index 000000000..9e23da905 --- /dev/null +++ b/hw/mcu/arc/src/ext/sdk/board/emsk/spi/dw_spi_obj.c @@ -0,0 +1,322 @@ +/* ------------------------------------------ + * Copyright (c) 2017, Synopsys, Inc. All rights reserved. + + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + + * 1) Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + + * 2) 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. + + * 3) Neither the name of the Synopsys, Inc., nor the names of its contributors may + * be used to endorse or promote products derived from this software without + * specific prior written permission. + + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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. + * + * \version 2017.03 + * \date 2014-07-03 + * \author Huaqi Fang(Huaqi.Fang@synopsys.com) +--------------------------------------------- */ + +/** + * \defgroup BOARD_EMSK_DRV_DW_SPI_OBJ EMSK DW SPI Object + * \ingroup BOARD_EMSK_DRIVER + * \brief EMSK Designware SPI Objects + * \details + * realize the EMSK board spi object using designware spi device driver, + * only need to realize some designware spi structures combine with EMSK spi + * hardware resource. just like cpp class instantiation. + */ + +/** + * \file + * \ingroup BOARD_EMSK_DRV_DW_SPI_OBJ + * \brief designware spi object instantiation on emsk + */ + +/** + * \addtogroup BOARD_EMSK_DRV_DW_SPI_OBJ + * @{ + */ +#include "inc/arc/arc.h" +#include "inc/arc/arc_builtin.h" +#include "inc/embARC_toolchain.h" +#include "inc/embARC_error.h" +#include "inc/arc/arc_exception.h" + +#include "device/designware/spi/dw_spi.h" +#include "board/emsk/spi/dw_spi_obj.h" + +#include "board/emsk/emsk.h" + +#ifdef ARC_FEATURE_DMP_PERIPHERAL +#define PERIPHERAL_BASE ARC_FEATURE_DMP_PERIPHERAL +#else +#define PERIPHERAL_BASE _arc_aux_read(AUX_DMP_PERIPHERAL) +#endif + +/** + * \name EMSK DesignWare SPI 0 Object Instantiation + * @{ + */ +#if (USE_DW_SPI_0) +static void dw_spi_0_isr(void *ptr); +#define DW_SPI_0_RELBASE (REL_REGBASE_SPI0) /*!< designware spi 0 relative baseaddr */ +#define DW_SPI_0_INTNO (INTNO_SPI_MASTER) /*!< designware spi 0 interrupt number */ + +#define DW_SPI_0_TX_FIFO_LEN (32) +#define DW_SPI_0_RX_FIFO_LEN (32) + +#define DW_SPI_0_SUPPORTED_MODE DW_SPI_MASTER_SUPPORTED + +DEV_SPI dw_spi_0; /*!< designware spi object */ +DW_SPI_CTRL dw_spi_0_ctrl; /*!< designware spi 0 ctrl */ +#if HW_VERSION >= 22 +static uint32_t spi_mst_cs_ctrl_creg = 0; +#endif + +/** designware spi 0 open */ +static int32_t dw_spi_0_open (uint32_t mode, uint32_t param) +{ + return dw_spi_open(&dw_spi_0, mode, param); +} +/** designware spi 0 close */ +static int32_t dw_spi_0_close (void) +{ + return dw_spi_close(&dw_spi_0); +} +/** designware spi 0 control */ +static int32_t dw_spi_0_control (uint32_t ctrl_cmd, void *param) +{ +#if HW_VERSION >= 22 + int32_t ercd; + ercd = dw_spi_control(&dw_spi_0, ctrl_cmd, param); + if (ctrl_cmd == SPI_CMD_MST_SEL_DEV) { + _arc_write_uncached_32((void *)spi_mst_cs_ctrl_creg, 1 << ((uint32_t)param)); + } else if (ctrl_cmd == SPI_CMD_MST_DSEL_DEV) { + _arc_write_uncached_32((void *)spi_mst_cs_ctrl_creg, 0); + } + return ercd; +#else + return dw_spi_control(&dw_spi_0, ctrl_cmd, param); +#endif +} +/** designware spi 0 write */ +static int32_t dw_spi_0_write (const void *data, uint32_t len) +{ + return dw_spi_write(&dw_spi_0, data, len); +} +/** designware spi 0 close */ +static int32_t dw_spi_0_read (void *data, uint32_t len) +{ + return dw_spi_read(&dw_spi_0, data, len); +} +/** designware spi 0 interrupt routine */ +static void dw_spi_0_isr(void *ptr) +{ + dw_spi_isr(&dw_spi_0, ptr); +} +/** install designware spi 0 to system */ +static void dw_spi_0_install(void) +{ + uint32_t spi_abs_base = 0; + DEV_SPI *dw_spi_ptr = &dw_spi_0; + DEV_SPI_INFO *dw_spi_info_ptr = &(dw_spi_0.spi_info); + DW_SPI_CTRL *dw_spi_ctrl_ptr = &dw_spi_0_ctrl; + DW_SPI_REG *dw_spi_reg_ptr; + + /** + * get absolute designware base address + */ + spi_abs_base = (uint32_t)PERIPHERAL_BASE + DW_SPI_0_RELBASE; + +#if HW_VERSION >= 22 + spi_mst_cs_ctrl_creg = spi_abs_base + REL_REGBASE_SPI_MST_CS_CTRL; +#endif + + dw_spi_reg_ptr = (DW_SPI_REG *)spi_abs_base; + + /** spi info init */ + dw_spi_info_ptr->spi_ctrl = (void *)dw_spi_ctrl_ptr; + dw_spi_info_ptr->status = DEV_DISABLED; + dw_spi_info_ptr->freq = 1000; + dw_spi_info_ptr->opn_cnt = 0; + dw_spi_info_ptr->mode = DEV_MASTER_MODE; + dw_spi_info_ptr->clk_mode = SPI_CLK_MODE_DEFAULT; + dw_spi_info_ptr->slave = SPI_SLAVE_NOT_SELECTED; + dw_spi_info_ptr->dfs = SPI_DFS_DEFAULT; + dw_spi_info_ptr->dummy = 0xff; + + /* spi ctrl init */ + /* Variables which should be set during object implementation */ + dw_spi_ctrl_ptr->dw_spi_regs = dw_spi_reg_ptr; + dw_spi_ctrl_ptr->intno = DW_SPI_0_INTNO; + dw_spi_ctrl_ptr->support_modes = DW_SPI_0_SUPPORTED_MODE; + dw_spi_ctrl_ptr->tx_fifo_len = DW_SPI_0_TX_FIFO_LEN; + dw_spi_ctrl_ptr->rx_fifo_len = DW_SPI_0_TX_FIFO_LEN; + dw_spi_ctrl_ptr->dw_apb_bus_freq = CLK_BUS_APB; + dw_spi_ctrl_ptr->dw_spi_int_handler = dw_spi_0_isr; + /* Variables which always change during spi operation */ + dw_spi_ctrl_ptr->int_status = 0; + + /** spi dev init */ + dw_spi_ptr->spi_open = dw_spi_0_open; + dw_spi_ptr->spi_close = dw_spi_0_close; + dw_spi_ptr->spi_control = dw_spi_0_control; + dw_spi_ptr->spi_write = dw_spi_0_write; + dw_spi_ptr->spi_read = dw_spi_0_read; +} +#endif /* USE_DW_SPI_0 */ +/** @} end of name */ + +/** + * \name EMSK DesignWare SPI 1 Object Instantiation + * @{ + */ +#if (USE_DW_SPI_1) +static void dw_spi_1_isr(void *ptr); +#define DW_SPI_1_RELBASE (REL_REGBASE_SPI1) /*!< designware spi 1 relative baseaddr */ +#define DW_SPI_1_INTNO (INTNO_SPI_SLAVE) /*!< designware spi 1 interrupt number */ + +#define DW_SPI_1_TX_FIFO_LEN (32) +#define DW_SPI_1_RX_FIFO_LEN (32) + +#define DW_SPI_1_SUPPORTED_MODE DW_SPI_SLAVE_SUPPORTED + +DEV_SPI dw_spi_1; /*!< designware spi 1 object */ +DW_SPI_CTRL dw_spi_1_ctrl; /*!< designware spi 1 ctrl */ + +/** designware spi 1 open */ +static int32_t dw_spi_1_open (uint32_t mode, uint32_t param) +{ + return dw_spi_open(&dw_spi_1, mode, param); +} +/** designware spi 1 close */ +static int32_t dw_spi_1_close (void) +{ + return dw_spi_close(&dw_spi_1); +} +/** designware spi 1 control */ +static int32_t dw_spi_1_control (uint32_t ctrl_cmd, void *param) +{ + return dw_spi_control(&dw_spi_1, ctrl_cmd, param); +} +/** designware spi 1 write */ +static int32_t dw_spi_1_write (const void *data, uint32_t len) +{ + return dw_spi_write(&dw_spi_1, data, len); +} +/** designware spi 1 close */ +static int32_t dw_spi_1_read (void *data, uint32_t len) +{ + return dw_spi_read(&dw_spi_1, data, len); +} +/** designware spi 1 interrupt routine */ +static void dw_spi_1_isr(void *ptr) +{ + dw_spi_isr(&dw_spi_1, ptr); +} +/** install designware spi 1 to system */ +static void dw_spi_1_install(void) +{ + uint32_t spi_abs_base = 0; + DEV_SPI *dw_spi_ptr = &dw_spi_1; + DEV_SPI_INFO *dw_spi_info_ptr = &(dw_spi_1.spi_info); + DW_SPI_CTRL *dw_spi_ctrl_ptr = &dw_spi_1_ctrl; + DW_SPI_REG *dw_spi_reg_ptr; + + /** + * get absolute designware base address + */ + spi_abs_base = (uint32_t)PERIPHERAL_BASE + DW_SPI_1_RELBASE; + dw_spi_reg_ptr = (DW_SPI_REG *)spi_abs_base; + + /** spi info init */ + dw_spi_info_ptr->spi_ctrl = (void *)dw_spi_ctrl_ptr; + dw_spi_info_ptr->status = DEV_DISABLED; + dw_spi_info_ptr->freq = 1000; + dw_spi_info_ptr->opn_cnt = 0; + dw_spi_info_ptr->mode = DEV_SLAVE_MODE; + dw_spi_info_ptr->clk_mode = SPI_CLK_MODE_DEFAULT; + dw_spi_info_ptr->slave = SPI_SLAVE_NOT_SELECTED; + dw_spi_info_ptr->dfs = SPI_DFS_DEFAULT; + dw_spi_info_ptr->dummy = 0xff; + + /* spi ctrl init */ + /* Variables which should be set during object implementation */ + dw_spi_ctrl_ptr->dw_spi_regs = dw_spi_reg_ptr; + dw_spi_ctrl_ptr->intno = DW_SPI_1_INTNO; + dw_spi_ctrl_ptr->support_modes = DW_SPI_1_SUPPORTED_MODE; + dw_spi_ctrl_ptr->tx_fifo_len = DW_SPI_1_TX_FIFO_LEN; + dw_spi_ctrl_ptr->rx_fifo_len = DW_SPI_1_TX_FIFO_LEN; + dw_spi_ctrl_ptr->dw_apb_bus_freq = CLK_BUS_APB; + dw_spi_ctrl_ptr->dw_spi_int_handler = dw_spi_1_isr; + /* Variables which always change during spi operation */ + dw_spi_ctrl_ptr->int_status = 0; + + /** spi dev init */ + dw_spi_ptr->spi_open = dw_spi_1_open; + dw_spi_ptr->spi_close = dw_spi_1_close; + dw_spi_ptr->spi_control = dw_spi_1_control; + dw_spi_ptr->spi_write = dw_spi_1_write; + dw_spi_ptr->spi_read = dw_spi_1_read; +} +#endif /* USE_DW_SPI_1 */ +/** @} end of name */ + +/** get one designware device structure */ +DEV_SPI_PTR spi_get_dev(int32_t spi_id) +{ + static uint32_t install_flag = 0; + + /* install device objects */ + if (install_flag == 0) { + install_flag = 1; + dw_spi_all_install(); + } + + switch (spi_id) { +#if (USE_DW_SPI_0) + case DW_SPI_0_ID: + return &dw_spi_0; + break; +#endif +#if (USE_DW_SPI_1) + case DW_SPI_1_ID: + return &dw_spi_1; + break; +#endif + default: + break; + } + return NULL; +} + +/** + * \brief install all spi objects + * \note \b MUST be called during system init + */ +void dw_spi_all_install(void) +{ +#if (USE_DW_SPI_0) + dw_spi_0_install(); +#endif +#if (USE_DW_SPI_1) + dw_spi_1_install(); +#endif +} + +/** @} end of group BOARD_EMSK_DRV_DW_SPI_OBJ */ diff --git a/hw/mcu/arc/src/ext/sdk/board/emsk/spi/dw_spi_obj.h b/hw/mcu/arc/src/ext/sdk/board/emsk/spi/dw_spi_obj.h new file mode 100644 index 000000000..4408d2b19 --- /dev/null +++ b/hw/mcu/arc/src/ext/sdk/board/emsk/spi/dw_spi_obj.h @@ -0,0 +1,82 @@ +/* ------------------------------------------ + * Copyright (c) 2017, Synopsys, Inc. All rights reserved. + + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + + * 1) Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + + * 2) 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. + + * 3) Neither the name of the Synopsys, Inc., nor the names of its contributors may + * be used to endorse or promote products derived from this software without + * specific prior written permission. + + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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. + * + * \version 2017.03 + * \date 2014-07-03 + * \author Huaqi Fang(Huaqi.Fang@synopsys.com) +--------------------------------------------- */ +/** + * \file + * \ingroup BOARD_EMSK_DRV_DW_SPI_OBJ + * \brief header file of designware spi object instantiation on emsk + */ + +/** + * \addtogroup BOARD_EMSK_DRV_DW_SPI_OBJ + * @{ + */ +#ifndef _DW_SPI_OBJ_H_ +#define _DW_SPI_OBJ_H_ + +#include "device/device_hal/inc/dev_spi.h" + +/** + * \name DesignWare SPI Object Number + * @{ + */ +#define DW_SPI_NUM (2) /*!< DesignWare SPI valid number */ +/** @} end of name */ + +/** + * \name Designware SPI Object ID Macros + * @{ + */ +#define DW_SPI_0_ID 0 /*!< SPI 0 id macro (master node) */ +#define DW_SPI_1_ID 1 /*!< SPI 1 id macro (slave node) */ +/** @} end of name */ + +/** + * \name Designware SPI Object Control Macros + * @{ + */ +#define USE_DW_SPI_0 1 /*!< enable use designware SPI 0 */ +#define USE_DW_SPI_1 1 /*!< enable use designware SPI 1 */ +/** @} end of name */ + +#ifdef __cplusplus +extern "C" { +#endif + +extern void dw_spi_all_install(void); + +#ifdef __cplusplus +} +#endif + +#endif /* _DW_SPI_OBJ_H_ */ +/** @} end of group BOARD_EMSK_DRV_DW_SPI_OBJ */ diff --git a/hw/mcu/arc/src/ext/sdk/board/emsk/uart/dw_uart_obj.c b/hw/mcu/arc/src/ext/sdk/board/emsk/uart/dw_uart_obj.c new file mode 100644 index 000000000..f83e70487 --- /dev/null +++ b/hw/mcu/arc/src/ext/sdk/board/emsk/uart/dw_uart_obj.c @@ -0,0 +1,266 @@ +/* ------------------------------------------ + * Copyright (c) 2016, Synopsys, Inc. All rights reserved. + + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + + * 1) Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + + * 2) 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. + + * 3) Neither the name of the Synopsys, Inc., nor the names of its contributors may + * be used to endorse or promote products derived from this software without + * specific prior written permission. + + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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. + * + * \version 2016.05 + * \date 2014-07-03 + * \author Huaqi Fang(Huaqi.Fang@synopsys.com) +--------------------------------------------- */ + +/** + * \defgroup BOARD_EMSK_DRV_DW_UART_OBJ EMSK DW UART Object + * \ingroup BOARD_EMSK_DRIVER + * \brief EMSK Designware UART Objects + * \details + * Realize the EMSK board uart object using Designware uart device driver, + * only need to realize some Designware uart structures combine with EMSK uart + * hardware resource. just like cpp class instantiation. + */ + +/** + * \file + * \ingroup BOARD_EMSK_DRV_DW_UART_OBJ + * \brief designware uart object instantiation on emsk + */ + +/** + * \addtogroup BOARD_EMSK_DRV_DW_UART_OBJ + * @{ + */ +#include "inc/arc/arc.h" +#include "inc/arc/arc_builtin.h" +#include "inc/embARC_toolchain.h" +#include "inc/embARC_error.h" + +#include "inc/arc/arc_exception.h" +#include "device/designware/uart/dw_uart.h" +#include "board/emsk/uart/dw_uart_obj.h" + +#include "board/emsk/emsk.h" + +#ifdef ARC_FEATURE_DMP_PERIPHERAL +#define PERIPHERAL_BASE ARC_FEATURE_DMP_PERIPHERAL +#else +#define PERIPHERAL_BASE _arc_aux_read(AUX_DMP_PERIPHERAL) +#endif + +#define DW_UART_FIFO_LEN 32 + +/** + * \name EMSK DesignWare UART 0 Object Instantiation + * @{ + */ +#if (USE_DW_UART_0) +static void dw_uart_0_isr(void *ptr); +#define DW_UART_0_RELBASE (REL_REGBASE_UART0) /*!< designware uart 0 relative baseaddr */ +#define DW_UART_0_INTNO (INTNO_UART0) /*!< designware uart 0 interrupt number */ + +DEV_UART dw_uart_0; /*!< designware uart object */ +DW_UART_CTRL dw_uart_0_ctrl = { /*!< designware uart 0 ctrl */ + 0, CLK_BUS_APB, DW_UART_0_INTNO, (INT_HANDLER)dw_uart_0_isr, + DW_UART_FIFO_LEN, DW_UART_FIFO_LEN, 0 +}; + +/** designware uart 0 open */ +static int32_t dw_uart_0_open (uint32_t baud) +{ + return dw_uart_open(&dw_uart_0, baud); +} +/** designware uart 0 close */ +static int32_t dw_uart_0_close (void) +{ + return dw_uart_close(&dw_uart_0); +} +/** designware uart 0 control */ +static int32_t dw_uart_0_control (uint32_t ctrl_cmd, void *param) +{ + return dw_uart_control(&dw_uart_0, ctrl_cmd, param); +} +/** designware uart 0 write */ +static int32_t dw_uart_0_write (const void *data, uint32_t len) +{ + return dw_uart_write(&dw_uart_0, data, len); +} +/** designware uart 0 close */ +static int32_t dw_uart_0_read (void *data, uint32_t len) +{ + return dw_uart_read(&dw_uart_0, data, len); +} +/** designware uart 0 interrupt rountine */ +static void dw_uart_0_isr(void *ptr) +{ + dw_uart_isr(&dw_uart_0, ptr); +} +/** install designware uart 0 to system */ +static void dw_uart_0_install(void) +{ + uint32_t uart_abs_base = 0; + DEV_UART *dw_uart_ptr = &dw_uart_0; + DEV_UART_INFO *dw_uart_info_ptr = &(dw_uart_0.uart_info); + DW_UART_CTRL *dw_uart_ctrl_ptr = &dw_uart_0_ctrl; + + /** + * get absolute designware base address + */ + uart_abs_base = (uint32_t)PERIPHERAL_BASE + DW_UART_0_RELBASE; + dw_uart_ctrl_ptr->dw_uart_regbase = uart_abs_base; + + /** uart info init */ + dw_uart_info_ptr->uart_ctrl = (void *)dw_uart_ctrl_ptr; + dw_uart_info_ptr->opn_cnt = 0; + dw_uart_info_ptr->status = 0; + dw_uart_info_ptr->baudrate = UART_BAUDRATE_115200; /* default 115200bps */ + + /** uart dev init */ + dw_uart_ptr->uart_open = dw_uart_0_open; + dw_uart_ptr->uart_close = dw_uart_0_close; + dw_uart_ptr->uart_control = dw_uart_0_control; + dw_uart_ptr->uart_write = dw_uart_0_write; + dw_uart_ptr->uart_read = dw_uart_0_read; + +} +#endif /* USE_DW_UART_0 */ +/** @} end of name */ + +/** + * \name EMSK DesignWare UART 1 Object Instantiation + * @{ + */ +#if (USE_DW_UART_1) +static void dw_uart_1_isr(void *ptr); +#define DW_UART_1_RELBASE (REL_REGBASE_UART1) /*!< designware uart 1 relative baseaddr */ +#define DW_UART_1_INTNO (INTNO_UART1) /*!< designware uart 1 interrupt number */ + +DEV_UART dw_uart_1; /*!< designware uart 1 object */ +DW_UART_CTRL dw_uart_1_ctrl = { /*!< designware uart 1 ctrl */ + 0, CLK_BUS_APB, DW_UART_1_INTNO, (INT_HANDLER)dw_uart_1_isr, + DW_UART_FIFO_LEN, DW_UART_FIFO_LEN, 0 +}; + +/** designware uart 1 open */ +static int32_t dw_uart_1_open (uint32_t baud) +{ + return dw_uart_open(&dw_uart_1, baud); +} +/** designware uart 1 close */ +static int32_t dw_uart_1_close (void) +{ + return dw_uart_close(&dw_uart_1); +} +/** designware uart 1 control */ +static int32_t dw_uart_1_control (uint32_t ctrl_cmd, void *param) +{ + return dw_uart_control(&dw_uart_1, ctrl_cmd, param); +} +/** designware uart 1 write */ +static int32_t dw_uart_1_write (const void *data, uint32_t len) +{ + return dw_uart_write(&dw_uart_1, data, len); +} +/** designware uart 1 close */ +static int32_t dw_uart_1_read (void *data, uint32_t len) +{ + return dw_uart_read(&dw_uart_1, data, len); +} +/** designware uart 1 interrupt routine */ +static void dw_uart_1_isr(void *ptr) +{ + dw_uart_isr(&dw_uart_1, ptr); +} +/** install designware uart 1 to system */ +static void dw_uart_1_install(void) +{ + uint32_t uart_abs_base = 0; + DEV_UART *dw_uart_ptr = &dw_uart_1; + DEV_UART_INFO *dw_uart_info_ptr = &(dw_uart_1.uart_info); + DW_UART_CTRL *dw_uart_ctrl_ptr = &dw_uart_1_ctrl; + + /** + * get absolute designware base address + */ + uart_abs_base = (uint32_t)PERIPHERAL_BASE + DW_UART_1_RELBASE; + dw_uart_ctrl_ptr->dw_uart_regbase = uart_abs_base; + + /** uart info init */ + dw_uart_info_ptr->uart_ctrl = (void *)dw_uart_ctrl_ptr; + dw_uart_info_ptr->opn_cnt = 0; + dw_uart_info_ptr->status = 0; + dw_uart_info_ptr->baudrate = UART_BAUDRATE_115200; /* default 115200bps */ + + /** uart dev init */ + dw_uart_ptr->uart_open = dw_uart_1_open; + dw_uart_ptr->uart_close = dw_uart_1_close; + dw_uart_ptr->uart_control = dw_uart_1_control; + dw_uart_ptr->uart_write = dw_uart_1_write; + dw_uart_ptr->uart_read = dw_uart_1_read; +} +#endif /* USE_DW_UART_1 */ +/** @} end of name */ + +/** get one designware device structure */ +DEV_UART_PTR uart_get_dev(int32_t uart_id) +{ + static uint32_t install_flag = 0; + + /* intall device objects */ + if (install_flag == 0) { + install_flag = 1; + dw_uart_all_install(); + } + + switch (uart_id) { +#if (USE_DW_UART_0) + case DW_UART_0_ID: + return &dw_uart_0; + break; +#endif +#if (USE_DW_UART_1) + case DW_UART_1_ID: + return &dw_uart_1; + break; +#endif + default: + break; + } + return NULL; +} + +/** + * \brief install all uart objects + * \note \b MUST be called during system init + */ +void dw_uart_all_install(void) +{ +#if (USE_DW_UART_0) + dw_uart_0_install(); +#endif +#if (USE_DW_UART_1) + dw_uart_1_install(); +#endif +} + +/** @} end of group BOARD_EMSK_DRV_DW_UART_OBJ */ diff --git a/hw/mcu/arc/src/ext/sdk/board/emsk/uart/dw_uart_obj.h b/hw/mcu/arc/src/ext/sdk/board/emsk/uart/dw_uart_obj.h new file mode 100644 index 000000000..6fe2d13d2 --- /dev/null +++ b/hw/mcu/arc/src/ext/sdk/board/emsk/uart/dw_uart_obj.h @@ -0,0 +1,89 @@ +/* ------------------------------------------ + * Copyright (c) 2016, Synopsys, Inc. All rights reserved. + + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + + * 1) Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + + * 2) 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. + + * 3) Neither the name of the Synopsys, Inc., nor the names of its contributors may + * be used to endorse or promote products derived from this software without + * specific prior written permission. + + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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. + * + * \version 2016.05 + * \date 2014-07-03 + * \author Huaqi Fang(Huaqi.Fang@synopsys.com) +--------------------------------------------- */ +/** + * \file + * \ingroup BOARD_EMSK_DRV_DW_UART_OBJ + * \brief header file of designware uart object instantiation on emsk + */ + +/** + * \addtogroup BOARD_EMSK_DRV_DW_UART_OBJ + * @{ + */ +#ifndef _DW_UART_OBJ_H_ +#define _DW_UART_OBJ_H_ + +#include "device/device_hal/inc/dev_uart.h" + +/** + * \name DesignWare UART Object Number + * @{ + */ +#define DW_UART_NUM (2) /*!< DesignWare UART valid number */ +/** @} end of name */ + +/** + * \name Designware UART Object ID Macros + * @{ + */ +#define DW_UART_0_ID 0 /*!< uart 0 id macro */ +#define DW_UART_1_ID 1 /*!< uart 1 id macro */ +/** @} end of name */ + +/** + * \name Designware UART Object Control Macros + * @{ + */ +#define USE_DW_UART_0 1 /*!< enable use designware uart 0 */ +#define USE_DW_UART_1 1 /*!< enable use designware uart 1 */ +/** @} end of name */ + +/** + * \name Designware UART Ringbuffer Size Control Macros + * @{ + */ +#define MAX_SNDBUF_SIZE 256 /*!< max size of uart send buffer */ +#define MAX_RCVBUF_SIZE 10 /*!< max size of uart recv buffer */ +/** @} end of name */ + +#ifdef __cplusplus +extern "C" { +#endif + +extern void dw_uart_all_install(void); + +#ifdef __cplusplus +} +#endif + +#endif /* _DW_UART_OBJ_H_ */ diff --git a/hw/mcu/arc/src/ext/sdk/common/console_io.c b/hw/mcu/arc/src/ext/sdk/common/console_io.c new file mode 100644 index 000000000..064b10ffe --- /dev/null +++ b/hw/mcu/arc/src/ext/sdk/common/console_io.c @@ -0,0 +1,164 @@ +/* ------------------------------------------ + * Copyright (c) 2016, Synopsys, Inc. All rights reserved. + + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + + * 1) Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + + * 2) 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. + + * 3) Neither the name of the Synopsys, Inc., nor the names of its contributors may + * be used to endorse or promote products derived from this software without + * specific prior written permission. + + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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. + * + * \version 2016.05 + * \date 2014-06-23 + * \author Huaqi Fang(Huaqi.Fang@synopsys.com) +--------------------------------------------- */ + +/** + * \file + * \brief common io implementation + */ +#include +#include "inc/embARC_toolchain.h" +#include "inc/arc/arc_builtin.h" +#include "device/device_hal/inc/dev_uart.h" +#include "common/console_io.h" +#include "common/xprintf.h" +#include "board/board.h" + +#define CONSOLE_UART_ID BOARD_CONSOLE_UART_ID /*!< console uart id */ + +/*!< to indicate xprintf setup state(0 for not setup) */ +static int xprintf_setup_flag = 0; +static DEV_UART *console_uart; /*!< console uart device pointer */ + +/** put one char */ +int console_putchar(unsigned char chr) +{ + if (console_uart == NULL) { + return -1; + } + console_uart->uart_write((const void *)(&chr), 1); + return 0; +} + +/** put string */ +int console_putstr(const char *str, unsigned int len) +{ + if (console_uart == NULL) { + return -1; + } + return (int)console_uart->uart_write((const void *)(str), len); +} + +/** get one char*/ +int console_getchar(void) +{ + unsigned char data; + if (console_uart == NULL) { + return -1; + } + while (!console_uart->uart_read((void *)(&data), 1)); + + return (int)data; +} + +/** get string */ +int console_getstr(char *str, unsigned int len) +{ + if (console_uart == NULL) { + return -1; + } + return (int)console_uart->uart_read((void *)(str), len); +} + +#ifndef ENABLE_BANNER +#define ENABLE_BANNER 1 +#endif + +#ifndef EMBARC_BANNER_TYPE +#define EMBARC_BANNER_TYPE 1 +#endif + +static const char *embarc_banner = +#if EMBARC_BANNER_TYPE == 1 +"----------------------------------------------------------- \r\n\ + ____ _ ____ \r\n\ +| _ \\ _____ _____ _ __ ___ __| | __ ) _ _ \r\n\ +| |_) / _ \\ \\ /\\ / / _ \\ '__/ _ \\/ _` | _ \\| | | | \r\n\ +| __/ (_) \\ V V / __/ | | __/ (_| | |_) | |_| | \r\n\ +|_| \\___/ \\_/\\_/ \\___|_| \\___|\\__,_|____/ \\__, | \r\n\ + |___/ \r\n\ + _ _ ____ ____ \r\n\ + ___ _ __ ___ | |__ / \\ | _ \\ / ___| \r\n\ + / _ \\ '_ ` _ \\| '_ \\ / _ \\ | |_) | | \r\n\ + | __/ | | | | | |_) / ___ \\| _ <| |___ \r\n\ + \\___|_| |_| |_|_.__/_/ \\_\\_| \\_\\\\____| \r\n\ +------------------------------------------------------------ \r\n\ +"; +#else +"-----------------------------------------------------------------------------------------------\r\n\ + _/_/_/ _/ _/_/_/ \r\n\ + _/ _/ _/_/ _/ _/ _/ _/_/ _/ _/_/ _/_/ _/_/_/ _/ _/ _/ _/ \r\n\ + _/_/_/ _/ _/ _/ _/ _/ _/_/_/_/ _/_/ _/_/_/_/ _/ _/ _/_/_/ _/ _/ \r\n\ + _/ _/ _/ _/ _/ _/ _/ _/ _/ _/ _/ _/ _/ _/ _/ _/ \r\n\ + _/ _/_/ _/ _/ _/_/_/ _/ _/_/_/ _/_/_/ _/_/_/ _/_/_/ \r\n\ + _/ \r\n\ + _/_/ \r\n\ + _/ _/_/ _/_/_/ _/_/_/ \r\n\ + _/_/ _/_/_/ _/_/ _/_/_/ _/ _/ _/ _/ _/ \r\n\ + _/_/_/_/ _/ _/ _/ _/ _/ _/_/_/_/ _/_/_/ _/ \r\n\ + _/ _/ _/ _/ _/ _/ _/ _/ _/ _/ _/ \r\n\ + _/_/_/ _/ _/ _/ _/_/_/ _/ _/ _/ _/ _/_/_/ \r\n\ +------------------------------------------------------------------------------------------------\r\n\ +"; +#endif + +static void embarc_print_banner(void) +{ + xprintf("%s\r\n", embarc_banner); +} + +/** xprintf need functions api setup */ +void xprintf_setup(void) +{ + if (xprintf_setup_flag) { + return; + } + console_uart = uart_get_dev(CONSOLE_UART_ID); + console_uart->uart_open(BOARD_CONSOLE_UART_BAUD); + + xdev_in(console_getchar); + xdev_out(console_putchar); + +#if ENABLE_BANNER == 1 + embarc_print_banner(); +#endif + + xprintf("embARC Build Time: %s, %s\r\n", __DATE__, __TIME__); +#if defined(__GNU__) + xprintf("Compiler Version: ARC GNU, %s\r\n", __VERSION__); +#else + xprintf("Compiler Version: Metaware, %s\r\n", __VERSION__); +#endif + + xprintf_setup_flag = 1; +} + diff --git a/hw/mcu/arc/src/ext/sdk/common/console_io.h b/hw/mcu/arc/src/ext/sdk/common/console_io.h new file mode 100644 index 000000000..9fbae75d9 --- /dev/null +++ b/hw/mcu/arc/src/ext/sdk/common/console_io.h @@ -0,0 +1,57 @@ +/* ------------------------------------------ + * Copyright (c) 2016, Synopsys, Inc. All rights reserved. + + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + + * 1) Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + + * 2) 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. + + * 3) Neither the name of the Synopsys, Inc., nor the names of its contributors may + * be used to endorse or promote products derived from this software without + * specific prior written permission. + + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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. + * + * \version 2016.05 + * \date 2014-06-23 + * \author Huaqi Fang(Huaqi.Fang@synopsys.com) +--------------------------------------------- */ + +/** + * \file + * \brief common io implementation + */ +#ifndef _CONSOLE_IO_H_ +#define _CONSOLE_IO_H_ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +extern int console_putchar(unsigned char chr); +extern int console_putstr(const char *str, unsigned int len); +extern int console_getchar(void); +extern int console_getstr(char *str, unsigned int len); +extern void xprintf_setup(void); + +#ifdef __cplusplus +} +#endif + +#endif /* _CONSOLE_IO_H_ */ diff --git a/hw/mcu/arc/src/ext/sdk/common/xprintf.c b/hw/mcu/arc/src/ext/sdk/common/xprintf.c new file mode 100644 index 000000000..103ecc8d3 --- /dev/null +++ b/hw/mcu/arc/src/ext/sdk/common/xprintf.c @@ -0,0 +1,391 @@ +/*------------------------------------------------------------------------/ +/ Universal string handler for user console interface +/-------------------------------------------------------------------------/ +/ +/ Copyright (C) 2011, ChaN, all right reserved. +/ +/ * This software is a free software and there is NO WARRANTY. +/ * No restriction on use. You can use, modify and redistribute it for +/ personal, non-profit or commercial products UNDER YOUR RESPONSIBILITY. +/ * Redistributions of source code must retain the above copyright notice. +/ +/-------------------------------------------------------------------------*/ + +#include "xprintf.h" + +#if _USE_XFUNC_OUT +#include +void (*xfunc_out)(unsigned char); /* Pointer to the output stream */ +static char *outptr; + +/*----------------------------------------------*/ +/* Put a character */ +/*----------------------------------------------*/ + +void xputc (char c) +{ + if (_CR_CRLF && c == '\n') xputc('\r'); /* CR -> CRLF */ + + if (outptr) { + *outptr++ = (unsigned char)c; + return; + } + + if (xfunc_out) xfunc_out((unsigned char)c); +} + + + +/*----------------------------------------------*/ +/* Put a null-terminated string */ +/*----------------------------------------------*/ + +void xputs ( /* Put a string to the default device */ + const char* str /* Pointer to the string */ +) +{ + while (*str) + xputc(*str++); +} + + +void xfputs ( /* Put a string to the specified device */ + void(*func)(unsigned char), /* Pointer to the output function */ + const char* str /* Pointer to the string */ +) +{ + void (*pf)(unsigned char); + + + pf = xfunc_out; /* Save current output device */ + xfunc_out = func; /* Switch output to specified device */ + while (*str) /* Put the string */ + xputc(*str++); + xfunc_out = pf; /* Restore output device */ +} + + + +/*----------------------------------------------*/ +/* Formatted string output */ +/*----------------------------------------------*/ +/* xprintf("%d", 1234); "1234" + xprintf("%6d,%3d%%", -200, 5); " -200, 5%" + xprintf("%-6u", 100); "100 " + xprintf("%ld", 12345678L); "12345678" + xprintf("%04x", 0xA3); "00a3" + xprintf("%08LX", 0x123ABC); "00123ABC" + xprintf("%016b", 0x550F); "0101010100001111" + xprintf("%s", "String"); "String" + xprintf("%-4s", "abc"); "abc " + xprintf("%4s", "abc"); " abc" + xprintf("%c", 'a'); "a" + xprintf("%f", 10.0); +*/ + +void xvprintf ( + const char* fmt, /* Pointer to the format string */ + va_list arp /* Pointer to arguments */ +) +{ + unsigned int r, i, j, w, f; + unsigned long v; + char s[16], c, d, *p; + + + for (;;) { + c = *fmt++; /* Get a char */ + if (!c) break; /* End of format? */ + if (c != '%') { /* Pass through it if not a % sequense */ + xputc(c); continue; + } + f = 0; + c = *fmt++; /* Get first char of the sequense */ + if (c == '0') { /* Flag: '0' padded */ + f = 1; c = *fmt++; + } else { + if (c == '-') { /* Flag: left justified */ + f = 2; c = *fmt++; + } + } + for (w = 0; c >= '0' && c <= '9'; c = *fmt++) /* Minimum width */ + w = w * 10 + c - '0'; + if (c == 'l' || c == 'L') { /* Prefix: Size is long int */ + f |= 4; c = *fmt++; + } + if (!c) break; /* End of format? */ + d = c; + if (d >= 'a') d -= 0x20; + switch (d) { /* Type is... */ + case 'S' : /* String */ + p = va_arg(arp, char*); + for (j = 0; p[j]; j++) ; + while (!(f & 2) && j++ < w) xputc(' '); + xputs(p); + while (j++ < w) xputc(' '); + continue; + case 'C' : /* Character */ + xputc((char)va_arg(arp, int)); continue; + case 'B' : /* Binary */ + r = 2; break; + case 'O' : /* Octal */ + r = 8; break; + case 'D' : /* Signed decimal */ + case 'U' : /* Unsigned decimal */ + r = 10; break; + case 'X' : /* Hexdecimal */ + r = 16; break; + default: /* Unknown type (passthrough) */ + xputc(c); continue; + } + + /* Get an argument and put it in numeral */ + v = (f & 4) ? va_arg(arp, long) : ((d == 'D') ? (long)va_arg(arp, int) : (long)va_arg(arp, unsigned int)); + if (d == 'D' && (v & 0x80000000)) { + v = 0 - v; + f |= 8; + } + i = 0; + do { + d = (char)(v % r); v /= r; + if (d > 9) d += (c == 'x') ? 0x27 : 0x07; + s[i++] = d + '0'; + } while (v && i < sizeof(s)); + if ((f & 8) && (i < sizeof(s))) s[i++] = '-'; + j = i; d = (f & 1) ? '0' : ' '; + while (!(f & 2) && j++ < w) xputc(d); + do xputc(s[--i]); while(i); + while (j++ < w) xputc(' '); + } +} + + +void xprintf ( /* Put a formatted string to the default device */ + const char* fmt, /* Pointer to the format string */ + ... /* Optional arguments */ +) +{ + va_list arp; + + + va_start(arp, fmt); + xvprintf(fmt, arp); + va_end(arp); +} + + +void xsprintf ( /* Put a formatted string to the memory */ + char* buff, /* Pointer to the output buffer */ + const char* fmt, /* Pointer to the format string */ + ... /* Optional arguments */ +) +{ + va_list arp; + + + outptr = buff; /* Switch destination for memory */ + + va_start(arp, fmt); + xvprintf(fmt, arp); + va_end(arp); + + *outptr = 0; /* Terminate output string with a \0 */ + outptr = 0; /* Switch destination for device */ +} + + +void xfprintf ( /* Put a formatted string to the specified device */ + void(*func)(unsigned char), /* Pointer to the output function */ + const char* fmt, /* Pointer to the format string */ + ... /* Optional arguments */ +) +{ + va_list arp; + void (*pf)(unsigned char); + + + pf = xfunc_out; /* Save current output device */ + xfunc_out = func; /* Switch output to specified device */ + + va_start(arp, fmt); + xvprintf(fmt, arp); + va_end(arp); + + xfunc_out = pf; /* Restore output device */ +} + + + +/*----------------------------------------------*/ +/* Dump a line of binary dump */ +/*----------------------------------------------*/ + +void put_dump ( + const void* buff, /* Pointer to the array to be dumped */ + unsigned long addr, /* Heading address value */ + int len, /* Number of items to be dumped */ + int width /* Size of the items (DF_CHAR, DF_SHORT, DF_LONG) */ +) +{ + int i; + const unsigned char *bp; + const unsigned short *sp; + const unsigned long *lp; + + + xprintf("%08lX ", addr); /* address */ + + switch (width) { + case DW_CHAR: + bp = buff; + for (i = 0; i < len; i++) /* Hexdecimal dump */ + xprintf(" %02X", bp[i]); + xputc(' '); + for (i = 0; i < len; i++) /* ASCII dump */ + xputc((bp[i] >= ' ' && bp[i] <= '~') ? bp[i] : '.'); + break; + case DW_SHORT: + sp = buff; + do /* Hexdecimal dump */ + xprintf(" %04X", *sp++); + while (--len); + break; + case DW_LONG: + lp = buff; + do /* Hexdecimal dump */ + xprintf(" %08LX", *lp++); + while (--len); + break; + } + + xputc('\n'); +} + +#endif /* _USE_XFUNC_OUT */ + + + +#if _USE_XFUNC_IN +unsigned char (*xfunc_in)(void); /* Pointer to the input stream */ + +/*----------------------------------------------*/ +/* Get a line from the input */ +/*----------------------------------------------*/ + +int xgets ( /* 0:End of stream, 1:A line arrived */ + char* buff, /* Pointer to the buffer */ + int len /* Buffer length */ +) +{ + int c, i; + + + if (!xfunc_in) return 0; /* No input function specified */ + + i = 0; + for (;;) { + c = xfunc_in(); /* Get a char from the incoming stream */ + if (!c) return 0; /* End of stream? */ + if (c == '\r') break; /* End of line? */ + if (c == '\b' && i) { /* Back space? */ + i--; + if (_LINE_ECHO) xputc(c); + continue; + } + if (c >= ' ' && i < len - 1) { /* Visible chars */ + buff[i++] = c; + if (_LINE_ECHO) xputc(c); + } + } + buff[i] = 0; /* Terminate with a \0 */ + if (_LINE_ECHO) xputc('\n'); + return 1; +} + + +int xfgets ( /* 0:End of stream, 1:A line arrived */ + unsigned char (*func)(void), /* Pointer to the input stream function */ + char* buff, /* Pointer to the buffer */ + int len /* Buffer length */ +) +{ + unsigned char (*pf)(void); + int n; + + + pf = xfunc_in; /* Save current input device */ + xfunc_in = func; /* Switch input to specified device */ + n = xgets(buff, len); /* Get a line */ + xfunc_in = pf; /* Restore input device */ + + return n; +} + + +/*----------------------------------------------*/ +/* Get a value of the string */ +/*----------------------------------------------*/ +/* "123 -5 0x3ff 0b1111 0377 w " + ^ 1st call returns 123 and next ptr + ^ 2nd call returns -5 and next ptr + ^ 3rd call returns 1023 and next ptr + ^ 4th call returns 15 and next ptr + ^ 5th call returns 255 and next ptr + ^ 6th call fails and returns 0 +*/ + +int xatoi ( /* 0:Failed, 1:Successful */ + char **str, /* Pointer to pointer to the string */ + long *res /* Pointer to the valiable to store the value */ +) +{ + unsigned long val; + unsigned char c, r, s = 0; + + + *res = 0; + + while ((c = **str) == ' ') (*str)++; /* Skip leading spaces */ + + if (c == '-') { /* negative? */ + s = 1; + c = *(++(*str)); + } + + if (c == '0') { + c = *(++(*str)); + switch (c) { + case 'x': /* hexdecimal */ + r = 16; c = *(++(*str)); + break; + case 'b': /* binary */ + r = 2; c = *(++(*str)); + break; + default: + if (c <= ' ') return 1; /* single zero */ + if (c < '0' || c > '9') return 0; /* invalid char */ + r = 8; /* octal */ + } + } else { + if (c < '0' || c > '9') return 0; /* EOL or invalid char */ + r = 10; /* decimal */ + } + + val = 0; + while (c > ' ') { + if (c >= 'a') c -= 0x20; + c -= '0'; + if (c >= 17) { + c -= 7; + } + if (c >= r) return 0; /* invalid char for current radix */ + val = val * r + c; + c = *(++(*str)); + } + if (s) val = 0 - val; /* apply sign if needed */ + + *res = val; + return 1; +} + +#endif /* _USE_XFUNC_IN */ diff --git a/hw/mcu/arc/src/ext/sdk/common/xprintf.h b/hw/mcu/arc/src/ext/sdk/common/xprintf.h new file mode 100644 index 000000000..0485e8462 --- /dev/null +++ b/hw/mcu/arc/src/ext/sdk/common/xprintf.h @@ -0,0 +1,48 @@ +/*------------------------------------------------------------------------*/ +/* Universal string handler for user console interface (C)ChaN, 2011 */ +/*------------------------------------------------------------------------*/ + +#ifndef _STRFUNC +#define _STRFUNC + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#define _USE_XFUNC_OUT 1 /* 1: Use output functions */ +#define _CR_CRLF 1 /* 1: Convert \n ==> \r\n in the output char */ + +#define _USE_XFUNC_IN 1 /* 1: Use input function */ +#define _LINE_ECHO 1 /* 1: Echo back input chars in xgets function */ + +#if _USE_XFUNC_OUT +#define xdev_out(func) xfunc_out = (void(*)(unsigned char))(func) +extern void (*xfunc_out)(unsigned char); +extern void xputc (char c); +extern void xputs (const char* str); +extern void xfputs (void (*func)(unsigned char), const char* str); +extern void xvprintf (const char* fmt, va_list arp); +extern void xprintf (const char* fmt, ...); +extern void xsprintf (char* buff, const char* fmt, ...); +extern void xfprintf (void (*func)(unsigned char), const char* fmt, ...); +extern void put_dump (const void* buff, unsigned long addr, int len, int width); +#define DW_CHAR sizeof(char) +#define DW_SHORT sizeof(short) +#define DW_LONG sizeof(long) +#endif + +#if _USE_XFUNC_IN +#define xdev_in(func) xfunc_in = (unsigned char(*)(void))(func) +extern unsigned char (*xfunc_in)(void); +extern int xgets (char* buff, int len); +extern int xfgets (unsigned char (*func)(void), char* buff, int len); +extern int xatoi (char** str, long* res); +#endif + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/hw/mcu/arc/src/ext/sdk/device/designware/gpio/dw_gpio.c b/hw/mcu/arc/src/ext/sdk/device/designware/gpio/dw_gpio.c new file mode 100644 index 000000000..ce79414fc --- /dev/null +++ b/hw/mcu/arc/src/ext/sdk/device/designware/gpio/dw_gpio.c @@ -0,0 +1,481 @@ +/* ------------------------------------------ + * Copyright (c) 2016, Synopsys, Inc. All rights reserved. + + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + + * 1) Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + + * 2) 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. + + * 3) Neither the name of the Synopsys, Inc., nor the names of its contributors may + * be used to endorse or promote products derived from this software without + * specific prior written permission. + + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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. + * + * \version 2016.05 + * \date 2014-07-22 + * \author Wayne Ren(Wei.Ren@synopsys.com) +--------------------------------------------- */ + +/** + * \defgroup DEVICE_DW_GPIO Designware GPIO Driver + * \ingroup DEVICE_DW + * \brief Designware GPIO Driver Implementation + */ + +/** + * \file + * \brief designware gpio driver + * \ingroup DEVICE_DW_GPIO + * \brief Designware GPIO driver + */ +#include "inc/embARC_toolchain.h" +#include "inc/embARC_error.h" +#include "inc/arc/arc_exception.h" + +#include "device/designware/gpio/dw_gpio.h" + +/** check expressions used in DesignWare GPIO driver implementation */ +#define DW_GPIO_CHECK_EXP(EXPR, ERROR_CODE) CHECK_EXP(EXPR, ercd, ERROR_CODE, error_exit) + +#ifndef DISABLE_DEVICE_OBJECT_VALID_CHECK +/** valid check of uart info object */ +#define VALID_CHK_GPIO_INFO_OBJECT(gpioinfo_obj_ptr) { \ + DW_GPIO_CHECK_EXP((gpioinfo_obj_ptr)!=NULL, E_OBJ); \ + DW_GPIO_CHECK_EXP(((gpioinfo_obj_ptr)->gpio_ctrl)!=NULL, E_OBJ); \ + } +#endif + +/** + * \defgroup DEVICE_DW_GPIO_STATIC DesignWare GPIO Driver Static Functions + * \ingroup DEVICE_DW_GPIO + * \brief Static or inline functions, variables for DesignWare GPIO handle gpio operations, + * only used in this file + * @{ + */ +Inline uint32_t dw_gpio_read_ext(DW_GPIO_PORT_PTR port) +{ + return port->regs->EXT_PORTS[port->no]; +} + +Inline uint32_t dw_gpio_read_dir(DW_GPIO_PORT_PTR port) +{ + return port->regs->SWPORTS[port->no].DDR; +} + +Inline uint32_t dw_gpio_read_dr(DW_GPIO_PORT_PTR port) +{ + return port->regs->SWPORTS[port->no].DR; +} + +Inline uint32_t dw_gpio_read_mthd(DW_GPIO_PORT_PTR port) +{ + return port->regs->INTEN; +} + +Inline void dw_gpio_int_enable(DW_GPIO_PORT_PTR port, uint32_t bit_mask) +{ + port->regs->INTEN |= bit_mask; +} + +Inline void dw_gpio_int_disable(DW_GPIO_PORT_PTR port, uint32_t bit_mask) +{ + port->regs->INTEN &= (~bit_mask); +} + +Inline void dw_gpio_int_mask(DW_GPIO_PORT_PTR port, uint32_t bit_mask) +{ + port->regs->INTMASK |= bit_mask; +} + +Inline void dw_gpio_int_unmask(DW_GPIO_PORT_PTR port, uint32_t bit_mask) +{ + port->regs->INTMASK &= (~bit_mask); +} + +Inline uint32_t dw_gpio_int_read_level(DW_GPIO_PORT_PTR port) +{ + return port->regs->INTTYPE_LEVEL; +} + +Inline uint32_t dw_gpio_int_read_polarity(DW_GPIO_PORT_PTR port) +{ + return port->regs->INT_POLARITY; +} + +Inline uint32_t dw_gpio_int_read_debounce(DW_GPIO_PORT_PTR port) +{ + return port->regs->DEBOUNCE; +} + +Inline uint32_t dw_gpio_int_read_status(DW_GPIO_PORT_PTR port) +{ + return port->regs->INTSTATUS; +} + +Inline void dw_gpio_int_clear(DW_GPIO_PORT_PTR port, uint32_t bit_mask) +{ + port->regs->PORTA_EOI = bit_mask; +} + +static void dw_gpio_int_write_level(DW_GPIO_PORT_PTR port, uint32_t bit_mask, uint32_t bit_level) +{ + uint32_t reg_val; + + reg_val = port->regs->INTTYPE_LEVEL; + reg_val &= (~bit_mask); + bit_level &= bit_mask; + reg_val |= bit_level; + + port->regs->INTTYPE_LEVEL = reg_val; +} + +static void dw_gpio_int_write_polarity(DW_GPIO_PORT_PTR port, uint32_t bit_mask, uint32_t bit_polarity) +{ + uint32_t reg_val; + + reg_val = port->regs->INT_POLARITY; + + reg_val &= (~bit_mask); + bit_polarity &= bit_mask; + reg_val |= bit_polarity; + + port->regs->INT_POLARITY = reg_val; +} + +static void dw_gpio_int_write_debounce(DW_GPIO_PORT_PTR port, uint32_t bit_mask, uint32_t bit_debounce) +{ + uint32_t reg_val; + + reg_val = port->regs->DEBOUNCE; + + reg_val &= (~bit_mask); + bit_debounce &= bit_mask; + reg_val |= bit_debounce; + + port->regs->DEBOUNCE = reg_val; +} + +static void dw_gpio_set_int_cfg(DW_GPIO_PORT_PTR port, DEV_GPIO_INT_CFG *int_cfg) +{ + dw_gpio_int_write_level(port, int_cfg->int_bit_mask, int_cfg->int_bit_type); + dw_gpio_int_write_polarity(port, int_cfg->int_bit_mask, int_cfg->int_bit_polarity); + dw_gpio_int_write_debounce(port, int_cfg->int_bit_mask, int_cfg->int_bit_debounce); +} + +static void dw_gpio_get_int_cfg(DW_GPIO_PORT_PTR port, DEV_GPIO_INT_CFG *int_cfg) +{ + int_cfg->int_bit_type = dw_gpio_int_read_level(port) & int_cfg->int_bit_mask; + int_cfg->int_bit_polarity = dw_gpio_int_read_polarity(port) & int_cfg->int_bit_mask; + int_cfg->int_bit_debounce = dw_gpio_int_read_debounce(port) & int_cfg->int_bit_mask; +} + +static void dw_gpio_write_dr(DW_GPIO_PORT_PTR port, uint32_t bit_mask, uint32_t val) +{ + uint32_t temp_reg; + + temp_reg = port->regs->SWPORTS[port->no].DR; + temp_reg &= ~bit_mask; + val &= bit_mask; + temp_reg |= val; + + port->regs->SWPORTS[port->no].DR = temp_reg; +} + +static void dw_gpio_write_dir(DW_GPIO_PORT_PTR port, uint32_t bit_mask, uint32_t val) +{ + uint32_t temp_reg; + + temp_reg = port->regs->SWPORTS[port->no].DDR; + temp_reg &= ~bit_mask; + val &= bit_mask; + temp_reg |= val; + + port->regs->SWPORTS[port->no].DDR = temp_reg; +} + +static uint32_t dw_gpio_read_val(DW_GPIO_PORT_PTR port) +{ + uint32_t val; + + val = dw_gpio_read_ext(port) & (~dw_gpio_read_dir(port)); + val |= dw_gpio_read_dr(port) & dw_gpio_read_dir(port); + + return val; +} + +/** @} end of group DEVICE_DW_GPIO_STATIC */ + +/* interface for DEV_GPIO */ +/** Open designware gpio device with specified io direction configuration */ +int32_t dw_gpio_open(DEV_GPIO *gpio_obj, uint32_t dir) +{ + int32_t ercd = E_OK; + DEV_GPIO_INFO_PTR port_info_ptr = &(gpio_obj->gpio_info); + + /* START ERROR CHECK */ + VALID_CHK_GPIO_INFO_OBJECT(port_info_ptr); + /* END OF ERROR CHECK */ + + DW_GPIO_PORT_PTR port = (DW_GPIO_PORT_PTR)(port_info_ptr->gpio_ctrl); + DW_GPIO_CHECK_EXP(port->no <= DW_GPIO_PORT_D, E_OBJ); + + port_info_ptr->opn_cnt ++; + if (port_info_ptr->opn_cnt > 1) { /* opened before */ + if (dir == port_info_ptr->direction) { /* direction is the same */ + return E_OK; + } else { /* open with different direction */ + return E_OPNED; + } + } + + dw_gpio_write_dir(port, port->valid_bit_mask, dir); + + if (port->no == DW_GPIO_PORT_A) { + dw_gpio_int_clear(port, DW_GPIO_MASK_ALL); + dw_gpio_int_disable(port, DW_GPIO_MASK_ALL); + dw_gpio_int_unmask(port, DW_GPIO_MASK_ALL); + /* install gpio interrupt handler */ + int_handler_install(port->intno, port->int_handler); + int_disable(port->intno); + /** Set int type, int polarity and debounce configuration to default settings of device gpio */ + dw_gpio_set_int_cfg(port, (DEV_GPIO_INT_CFG *)(&gpio_int_cfg_default)); + port_info_ptr->method = dw_gpio_read_mthd(port); + } else { + port_info_ptr->method = DEV_GPIO_BITS_MTHD_DEFAULT; + } + + dw_gpio_write_dr(port, port->valid_bit_mask, 0); + + port_info_ptr->direction = dir; + port_info_ptr->extra = NULL; + +error_exit: + return ercd; +} + +/** Close designware gpio device */ +int32_t dw_gpio_close(DEV_GPIO *gpio_obj) +{ + int32_t ercd = E_OK; + DEV_GPIO_INFO_PTR port_info_ptr = &(gpio_obj->gpio_info); + + /* START ERROR CHECK */ + VALID_CHK_GPIO_INFO_OBJECT(port_info_ptr); + /* END OF ERROR CHECK */ + + DW_GPIO_PORT_PTR port = (DW_GPIO_PORT_PTR)(port_info_ptr->gpio_ctrl); + DW_GPIO_CHECK_EXP(port->no <= DW_GPIO_PORT_D, E_OBJ); + + DW_GPIO_CHECK_EXP(port_info_ptr->opn_cnt > 0, E_OK); + + port_info_ptr->opn_cnt --; + if (port_info_ptr->opn_cnt == 0) { + dw_gpio_write_dr(port, port->valid_bit_mask, 0); + dw_gpio_write_dir(port, port->valid_bit_mask, 0); + if (port->no == DW_GPIO_PORT_A) { + dw_gpio_int_clear(port, DW_GPIO_MASK_ALL); + dw_gpio_int_disable(port, DW_GPIO_MASK_ALL); + int_disable(port->intno); + } + + port_info_ptr->direction = 0; + port_info_ptr->method = 0; + port_info_ptr->extra = NULL; + } else { + ercd = E_OPNED; + } + +error_exit: + return ercd; +} + +/** Read designware gpio device value */ +int32_t dw_gpio_read(DEV_GPIO *gpio_obj, uint32_t *val, uint32_t mask) +{ + int32_t ercd = E_OK; + DEV_GPIO_INFO_PTR port_info_ptr = &(gpio_obj->gpio_info); + + /* START ERROR CHECK */ + VALID_CHK_GPIO_INFO_OBJECT(port_info_ptr); + /* END OF ERROR CHECK */ + + DW_GPIO_PORT_PTR port = (DW_GPIO_PORT_PTR)(port_info_ptr->gpio_ctrl); + DW_GPIO_CHECK_EXP(port->no <= DW_GPIO_PORT_D, E_OBJ); + DW_GPIO_CHECK_EXP(port_info_ptr->opn_cnt > 0, E_CLSED); + + DW_GPIO_CHECK_EXP(val!=NULL, E_PAR); + + //*val = dw_gpio_read_ext(port) & mask; + *val = dw_gpio_read_val(port) & mask; + +error_exit: + return ercd; +} + +/** Write designware gpio device value */ +int32_t dw_gpio_write(DEV_GPIO *gpio_obj, uint32_t val, uint32_t mask) +{ + int32_t ercd = E_OK; + DEV_GPIO_INFO_PTR port_info_ptr = &(gpio_obj->gpio_info); + + /* START ERROR CHECK */ + VALID_CHK_GPIO_INFO_OBJECT(port_info_ptr); + /* END OF ERROR CHECK */ + + DW_GPIO_PORT_PTR port = (DW_GPIO_PORT_PTR)(port_info_ptr->gpio_ctrl); + DW_GPIO_CHECK_EXP(port->no <= DW_GPIO_PORT_D, E_OBJ); + DW_GPIO_CHECK_EXP(port_info_ptr->opn_cnt > 0, E_CLSED); + + dw_gpio_write_dr(port, mask, val); + +error_exit: + return ercd; +} + +/** Control designware gpio device */ +int32_t dw_gpio_control(DEV_GPIO *gpio_obj, uint32_t ctrl_cmd, void *param) +{ + int32_t ercd = E_OK; + DEV_GPIO_INFO_PTR port_info_ptr = &(gpio_obj->gpio_info); + + /* START ERROR CHECK */ + VALID_CHK_GPIO_INFO_OBJECT(port_info_ptr); + /* END OF ERROR CHECK */ + + DW_GPIO_PORT_PTR port = (DW_GPIO_PORT_PTR)(port_info_ptr->gpio_ctrl); + DW_GPIO_CHECK_EXP(port->no <= DW_GPIO_PORT_D, E_OBJ); + DW_GPIO_CHECK_EXP(port_info_ptr->opn_cnt > 0, E_CLSED); + + uint32_t val32; /** to receive unsigned int value */ + + if (ctrl_cmd == GPIO_CMD_SET_BIT_DIR_INPUT) { + val32 = (uint32_t)param; + dw_gpio_write_dir(port, val32, DW_GPIO_INPUT_ALL); + port_info_ptr->direction = dw_gpio_read_dir(port); + } else if (ctrl_cmd == GPIO_CMD_SET_BIT_DIR_OUTPUT) { + val32 = (uint32_t)param; + dw_gpio_write_dir(port, val32, DW_GPIO_OUTPUT_ALL); + port_info_ptr->direction = dw_gpio_read_dir(port); + } else if (ctrl_cmd == GPIO_CMD_GET_BIT_DIR) { + DW_GPIO_CHECK_EXP((param!=NULL) && CHECK_ALIGN_4BYTES(param), E_PAR); + port_info_ptr->direction = dw_gpio_read_dir(port); + *((int32_t *)param) = port_info_ptr->direction; + } else { + DW_GPIO_CHECK_EXP(port->no == DW_GPIO_PORT_A, E_NOSPT); + /* output pin cannot be used as interrupt */ + DEV_GPIO_INT_CFG *gpio_int_cfg; + DEV_GPIO_BIT_ISR *port_bit_isr; + + switch (ctrl_cmd) { + case GPIO_CMD_SET_BIT_INT_CFG: + DW_GPIO_CHECK_EXP((param!=NULL) && CHECK_ALIGN_4BYTES(param), E_PAR); + gpio_int_cfg = (DEV_GPIO_INT_CFG *)param; + dw_gpio_set_int_cfg(port, gpio_int_cfg); + break; + case GPIO_CMD_GET_BIT_INT_CFG: + DW_GPIO_CHECK_EXP((param!=NULL) && CHECK_ALIGN_4BYTES(param), E_PAR); + gpio_int_cfg = (DEV_GPIO_INT_CFG *)param; + /** read configuration, each bit stands for different configuration */ + dw_gpio_get_int_cfg(port, gpio_int_cfg); + break; + case GPIO_CMD_SET_BIT_ISR: + DW_GPIO_CHECK_EXP((param!=NULL) && CHECK_ALIGN_4BYTES(param), E_PAR); + port_bit_isr = (DEV_GPIO_BIT_ISR *)param; + if (port_bit_isr->int_bit_ofs < port->gpio_bit_isr->int_bit_max_cnt) { + port->gpio_bit_isr->int_bit_handler_ptr[port_bit_isr->int_bit_ofs] = port_bit_isr->int_bit_handler; + } else { + ercd = E_PAR; + } + break; + case GPIO_CMD_GET_BIT_ISR: + DW_GPIO_CHECK_EXP((param!=NULL) && CHECK_ALIGN_4BYTES(param), E_PAR); + port_bit_isr = (DEV_GPIO_BIT_ISR *)param; + if (port_bit_isr->int_bit_ofs < port->gpio_bit_isr->int_bit_max_cnt) { + port_bit_isr->int_bit_handler = port->gpio_bit_isr->int_bit_handler_ptr[port_bit_isr->int_bit_ofs]; + } else { + ercd = E_PAR; + } + break; + case GPIO_CMD_ENA_BIT_INT: + val32 = (uint32_t)param; + dw_gpio_int_enable(port, val32); + port_info_ptr->method = dw_gpio_read_mthd(port); + if (port_info_ptr->method) { + int_enable(port->intno); + } + break; + case GPIO_CMD_DIS_BIT_INT: + val32 = (uint32_t)param; + dw_gpio_int_disable(port, val32); + port_info_ptr->method = dw_gpio_read_mthd(port); + if (port_info_ptr->method == 0) { + int_disable(port->intno); + } + break; + case GPIO_CMD_GET_BIT_MTHD: + DW_GPIO_CHECK_EXP((param!=NULL) && CHECK_ALIGN_4BYTES(param), E_PAR); + port_info_ptr->method = dw_gpio_read_mthd(port); + *((int32_t *)param) = port_info_ptr->method; + break; + default: + ercd = E_NOSPT; + break; + } + } +error_exit: + return ercd; +} + +/** designware gpio interrupt process */ +int32_t dw_gpio_isr_handler(DEV_GPIO *gpio_obj, void *ptr) +{ + int32_t ercd = E_OK; + DEV_GPIO_INFO_PTR port_info_ptr = &(gpio_obj->gpio_info); + + /* START ERROR CHECK */ + VALID_CHK_GPIO_INFO_OBJECT(port_info_ptr); + /* END OF ERROR CHECK */ + + DW_GPIO_PORT_PTR port = (DW_GPIO_PORT_PTR)(port_info_ptr->gpio_ctrl); + DW_GPIO_CHECK_EXP(port->no == DW_GPIO_PORT_A, E_NOSPT); + + uint32_t i, gpio_bit_isr_state; + uint32_t max_int_bit_count = 0; + + /** read interrupt status */ + gpio_bit_isr_state = dw_gpio_int_read_status(port); + + if (port->gpio_bit_isr) { + max_int_bit_count = (port->gpio_bit_isr->int_bit_max_cnt); + } else { + dw_gpio_int_clear(port, gpio_bit_isr_state); + } + + for (i=0; igpio_bit_isr->int_bit_handler_ptr[i]) { + port->gpio_bit_isr->int_bit_handler_ptr[i](gpio_obj); + } + dw_gpio_int_clear(port, (1< + +#include "inc/embARC_toolchain.h" +#include "inc/embARC_error.h" + +#include "inc/arc/arc_exception.h" + +#include "device/designware/iic/dw_iic_hal.h" +#include "device/designware/iic/dw_iic.h" + +/** check expressions used in DesignWare IIC driver implementation */ +#define DW_IIC_CHECK_EXP(EXPR, ERROR_CODE) CHECK_EXP(EXPR, ercd, ERROR_CODE, error_exit) + +#ifndef DISABLE_DEVICE_OBJECT_VALID_CHECK +/** valid check of iic info object */ +#define VALID_CHK_IIC_INFO_OBJECT(iicinfo_obj_ptr) { \ + DW_IIC_CHECK_EXP((iicinfo_obj_ptr)!=NULL, E_OBJ); \ + DW_IIC_CHECK_EXP(((iicinfo_obj_ptr)->iic_ctrl)!=NULL, E_OBJ); \ + } +#endif + +/** + * \name DesignWare IIC Interrupt Callback Routine Select Marcos + * \brief DesignWare IIC interrupt callback routines select macros definitions + * @{ + */ +#define DW_IIC_RDY_SND (1U) /*!< ready to send callback */ +#define DW_IIC_RDY_RCV (2U) /*!< ready to receive callback */ +/** @} */ + +/** + * \defgroup DEVICE_DW_IIC_STATIC DesignWare IIC Driver Static Functions + * \ingroup DEVICE_DW_IIC + * \brief Static or inline functions, variables for DesignWare IIC handle iic operations, + * only used in this file. + * @{ + */ +/** Disable designware iic device */ +Inline void dw_iic_disable(DW_IIC_REG *iic_reg_ptr) +{ + iic_reg_ptr->IC_ENABLE = DW_IIC_DISABLE; +} +/** Enable designware iic device */ +Inline void dw_iic_enable(DW_IIC_REG *iic_reg_ptr) +{ + iic_reg_ptr->IC_ENABLE = DW_IIC_ENABLE; +} + +/** Clear all designware iic interrupt */ +Inline void dw_iic_clear_interrupt_all(DW_IIC_REG *iic_reg_ptr) +{ + (void)iic_reg_ptr->IC_CLR_INTR; +} + +/** test whether iic is ready to write, 1 ready, 0 not ready */ +Inline int32_t dw_iic_putready(DW_IIC_REG *iic_reg_ptr) +{ + return ((iic_reg_ptr->IC_STATUS & IC_STATUS_TFNF) != 0); +} +/** test whether iic is ready to receive, 1 ready, 0 not ready */ +Inline int32_t dw_iic_getready(DW_IIC_REG *iic_reg_ptr) +{ + return ((iic_reg_ptr->IC_STATUS & IC_STATUS_RFNE) != 0); +} +/** Write data into IIC TX FIFO with STOP/RESTART Condition, and R/W bit */ +Inline void dw_iic_putdata(DW_IIC_REG *iic_reg_ptr, uint32_t data) +{ + iic_reg_ptr->IC_DATA_CMD = data; +} + +/** Read Data from IIC RX FIFO */ +Inline uint32_t dw_iic_getdata(DW_IIC_REG *iic_reg_ptr) +{ + return (iic_reg_ptr->IC_DATA_CMD) & 0xff; +} + +/** Enable designware iic bit interrupt with mask */ +Inline void dw_iic_unmask_interrupt(DW_IIC_REG *iic_reg_ptr, uint32_t mask) +{ + iic_reg_ptr->IC_INTR_MASK |= mask; +} + +/** Disable designware iic bit interrupt with mask */ +Inline void dw_iic_mask_interrupt(DW_IIC_REG *iic_reg_ptr, uint32_t mask) +{ + iic_reg_ptr->IC_INTR_MASK &= ~mask; +} + +/** Get TX FIFO Length */ +Inline uint32_t dw_iic_get_txfifo_len(DW_IIC_REG *iic_reg_ptr) +{ + uint32_t txfifolen; + + txfifolen = ((iic_reg_ptr->IC_COMP_PARAM_1 >> 16) & 0xff) + 1; + + return txfifolen; +} + +/** Get RX FIFO Length */ +Inline uint32_t dw_iic_get_rxfifo_len(DW_IIC_REG *iic_reg_ptr) +{ + uint32_t rxfifolen; + + rxfifolen = ((iic_reg_ptr->IC_COMP_PARAM_1 >> 8) & 0xff) + 1; + + return rxfifolen; +} + +/** Set designware iic transfer in 7bit of 10bit addressing mode as a master */ +Inline void dw_iic_set_mstaddr_mode(DW_IIC_REG *iic_reg_ptr, uint32_t mode) +{ +#if DW_IIC_DYNAMIC_TAR_UPDATE_SUPPORT + if (mode == IIC_7BIT_ADDRESS) { + iic_reg_ptr->IC_TAR &= ~IC_10BITADDR_MASTER; + } else { + iic_reg_ptr->IC_TAR |= IC_10BITADDR_MASTER; + } +#else + dw_iic_disable(iic_reg_ptr); + if (mode == IIC_7BIT_ADDRESS) { + iic_reg_ptr->IC_CON &= ~MST_10_BIT_ADDR_MODE; + } else { + iic_reg_ptr->IC_CON |= MST_10_BIT_ADDR_MODE; + } + dw_iic_enable(iic_reg_ptr); +#endif +} + +/** Set designware iic transfer in 7bit of 10bit addressing mode as a slave */ +Inline void dw_iic_set_slvaddr_mode(DW_IIC_REG *iic_reg_ptr, uint32_t mode) +{ + dw_iic_disable(iic_reg_ptr); + if (mode == IIC_7BIT_ADDRESS) { + iic_reg_ptr->IC_CON &= ~SLV_10_BIT_ADDR_MODE; + } else { + iic_reg_ptr->IC_CON |= SLV_10_BIT_ADDR_MODE; + } + dw_iic_enable(iic_reg_ptr); +} + +/** Set designware iic transfer target address for addressing any iic slave device as a master */ +Inline void dw_iic_set_taraddr(DW_IIC_REG *iic_reg_ptr, uint32_t address) +{ +#if DW_IIC_DYNAMIC_TAR_UPDATE_SUPPORT + iic_reg_ptr->IC_TAR &= ~(IC_TAR_10BIT_ADDR_MASK); + iic_reg_ptr->IC_TAR |= (IC_TAR_10BIT_ADDR_MASK & address); +#else + dw_iic_disable(iic_reg_ptr); + iic_reg_ptr->IC_TAR &= ~(IC_TAR_10BIT_ADDR_MASK); + iic_reg_ptr->IC_TAR |= (IC_TAR_10BIT_ADDR_MASK & address); + dw_iic_enable(iic_reg_ptr); +#endif +} + +/** Set designware iic slave address as a slave */ +Inline void dw_iic_set_slvaddr(DW_IIC_REG *iic_reg_ptr, uint32_t address) +{ + dw_iic_disable(iic_reg_ptr); + iic_reg_ptr->IC_SAR &= ~(IC_SAR_10BIT_ADDR_MASK); + iic_reg_ptr->IC_SAR |= (IC_SAR_10BIT_ADDR_MASK & address); + dw_iic_enable(iic_reg_ptr); +} + +/** Select speed mode, and return proper speed mode configuration */ +Inline uint32_t dw_iic_select_speedmode(uint32_t speedmode) +{ + uint32_t speedcfg; + + if (speedmode == IIC_SPEED_STANDARD) { + speedcfg = IC_CON_SPEED_STANDARD; + } else if (speedmode == IIC_SPEED_FAST) { + speedcfg = IC_CON_SPEED_FAST; + } else if (speedmode == IIC_SPEED_FASTPLUS) { + speedcfg = IC_CON_SPEED_FAST; + } else if (speedmode == IIC_SPEED_HIGH) { + speedcfg = IC_CON_SPEED_HIGH; + } else { + speedcfg = IC_CON_SPEED_HIGH; + } + return speedcfg; +} +/** Set designware iic speed mode */ +Inline void dw_iic_set_speedmode(DW_IIC_REG *iic_reg_ptr, uint32_t speedmode) +{ + uint32_t ic_con_val; + + dw_iic_disable(iic_reg_ptr); + ic_con_val = iic_reg_ptr->IC_CON & (~IC_CON_SPEED_MASK); + ic_con_val |= dw_iic_select_speedmode(speedmode); + iic_reg_ptr->IC_CON = ic_con_val; + dw_iic_enable(iic_reg_ptr); +} + +/** Set designware working mode as master or slave */ +Inline void dw_iic_set_working_mode(DW_IIC_REG *iic_reg_ptr, uint32_t mode) +{ + uint32_t ic_con_val; + dw_iic_disable(iic_reg_ptr); + ic_con_val = iic_reg_ptr->IC_CON & (~IC_CON_MST_SLV_MODE_MASK); + if (mode == DEV_MASTER_MODE) { + ic_con_val |= IC_CON_ENA_MASTER_MODE; + } else { + ic_con_val |= IC_CON_ENA_SLAVE_MODE; + } + dw_iic_enable(iic_reg_ptr); +} + +/** Set IC_CLK frequency by configuration the *CNT registers for different speed modes */ +Inline void dw_iic_set_scl_cnt(DW_IIC_REG *iic_reg_ptr, DW_IIC_SCL_CNT *scl_cnt) +{ + dw_iic_disable(iic_reg_ptr); + iic_reg_ptr->IC_SS_SCL_HCNT = scl_cnt->ss_scl_hcnt; + iic_reg_ptr->IC_SS_SCL_LCNT = scl_cnt->ss_scl_lcnt; + iic_reg_ptr->IC_FS_SCL_HCNT = scl_cnt->fs_scl_hcnt; + iic_reg_ptr->IC_FS_SCL_LCNT = scl_cnt->fs_scl_lcnt; + iic_reg_ptr->IC_HS_SCL_HCNT = scl_cnt->hs_scl_hcnt; + iic_reg_ptr->IC_HS_SCL_LCNT = scl_cnt->hs_scl_lcnt; + dw_iic_enable(iic_reg_ptr); +} + +/** Set spike suppression configuration */ +Inline void dw_iic_set_spike_len(DW_IIC_REG *iic_reg_ptr, DW_IIC_SPKLEN *spklen) +{ + dw_iic_disable(iic_reg_ptr); + iic_reg_ptr->IC_FS_SPKLEN = spklen->fs_spklen; + iic_reg_ptr->IC_HS_SPKLEN = spklen->hs_spklen; + dw_iic_enable(iic_reg_ptr); +} + +Inline void dw_iic_flush_tx(DW_IIC_REG *iic_reg_ptr) +{ + (void)iic_reg_ptr->IC_CLR_INTR; +} + +Inline void dw_iic_flush_rx(DW_IIC_REG *iic_reg_ptr) +{ +} + +static uint32_t dw_iic_get_slv_state(DW_IIC_REG *iic_reg_ptr) +{ + uint32_t status; + uint32_t slv_state = IIC_SLAVE_STATE_FREE; + + status = iic_reg_ptr->IC_RAW_INTR_STAT; + if (status & IC_INTR_STAT_GEN_CALL) { + /* General Call address is received and it is acknowledged */ + slv_state |= IIC_SLAVE_STATE_GC_REQ; + } + if (status & IC_INTR_STAT_RX_FULL) { + /* master is attempting to write data to this slave */ + slv_state |= IIC_SLAVE_STATE_WR_REQ; + } + if (status & IC_INTR_STAT_RD_REQ) { + /* master is attempting to read data from this slave */ + slv_state |= IIC_SLAVE_STATE_RD_REQ; + } + if (status & IC_INTR_STAT_RX_DONE) { + /* master does not acknowledge a transmitted byte, and transmission is done */ + slv_state |= IIC_SLAVE_STATE_RD_DONE; + status = iic_reg_ptr->IC_CLR_RX_DONE; + } + if (status & IC_INTR_STAT_START_DET) { + /* a START or RESTART condition has occurred */ + slv_state |= IIC_SLAVE_STATE_START; + status = iic_reg_ptr->IC_CLR_START_DET; /* Clear it when read */ + } + if (status & IC_INTR_STAT_STOP_DET) { + /* a STOP condition has occurred */ + slv_state |= IIC_SLAVE_STATE_STOP; + status = iic_reg_ptr->IC_CLR_STOP_DET; /* Clear it when read */ + } + if (status & (IC_INTR_STAT_TX_ABRT|IC_INTR_STAT_TX_OVER\ + |IC_INTR_STAT_RX_OVER|IC_INTR_STAT_RX_UNDER)) { + /* error case */ + slv_state |= IIC_SLAVE_STATE_ERROR; + status = iic_reg_ptr->IC_CLR_TX_ABRT; /* Clear it when read */ + status = iic_reg_ptr->IC_CLR_TX_OVER; + status = iic_reg_ptr->IC_CLR_RX_OVER; + status = iic_reg_ptr->IC_CLR_RX_UNDER; + } + + return slv_state; +} + +/** Init Designware IIC Device into Master mode */ +static void dw_iic_master_init(DW_IIC_CTRL *iic_ctrl_ptr, uint32_t speed_mode, uint32_t addr_mode, uint32_t tar_addr) +{ + uint32_t ic_con_val = 0; + DW_IIC_REG *iic_reg_ptr = iic_ctrl_ptr->dw_iic_regs; + + dw_iic_disable(iic_reg_ptr); + + /* disable all iic interrupt */ + iic_reg_ptr->IC_INTR_MASK = IC_INT_DISABLE_ALL; + + /* Set to 7bit addressing and update target address */ + iic_reg_ptr->IC_TAR = (tar_addr & IC_TAR_10BIT_ADDR_MASK) | IC_TAR_SPECIAL | IC_TAR_GC_OR_START; + /* master mode, restart enabled */ + ic_con_val = dw_iic_select_speedmode(speed_mode) | IC_CON_ENA_MASTER_MODE | IC_CON_RESTART_EN; + +#if DW_IIC_DYNAMIC_TAR_UPDATE_SUPPORT + if (addr_mode == IIC_10BIT_ADDRESS) { + iic_reg_ptr->IC_TAR |= MST_10_BIT_ADDR_MODE; + } +#else + if (addr_mode == IIC_10BIT_ADDRESS) { + ic_con_val |= MST_10_BIT_ADDR_MODE; + } +#endif + /* Set final IC_CON value */ + iic_reg_ptr->IC_CON = ic_con_val; + /* FIFO threshold settings */ + iic_reg_ptr->IC_TX_TL = IIC_TX_THRESHOLD; + iic_reg_ptr->IC_RX_TL = IIC_RX_THRESHOLD; + /* Master code settings */ + iic_reg_ptr->IC_HS_MADDR = iic_ctrl_ptr->iic_master_code; + dw_iic_enable(iic_reg_ptr); + + /* Clock Settings */ + dw_iic_set_scl_cnt(iic_reg_ptr, &(iic_ctrl_ptr->iic_scl_cnt)); + dw_iic_set_spike_len(iic_reg_ptr, &(iic_ctrl_ptr->iic_spklen)); +} + +/** Init Designware IIC Device into Slave mode */ +static void dw_iic_slave_init(DW_IIC_CTRL *iic_ctrl_ptr, uint32_t addr_mode, uint32_t slv_addr) +{ + uint32_t ic_con_val = 0; + DW_IIC_REG *iic_reg_ptr = iic_ctrl_ptr->dw_iic_regs; + + dw_iic_disable(iic_reg_ptr); + + /* disable all iic interrupt */ + iic_reg_ptr->IC_INTR_MASK = IC_INT_DISABLE_ALL; + + /* Set slave device address as a slave */ + iic_reg_ptr->IC_SAR = slv_addr & IC_SAR_10BIT_ADDR_MASK; + /* slave mode, 7 bit slave address */ + ic_con_val = IC_CON_ENA_SLAVE_MODE; + /* If addr mode select to be 10 bit address mode */ + if (addr_mode == IIC_10BIT_ADDRESS) { + ic_con_val |= SLV_10_BIT_ADDR_MODE; + } + + /* Set final IC_CON value */ + iic_reg_ptr->IC_CON = ic_con_val; + /* FIFO threshold settings */ + iic_reg_ptr->IC_TX_TL = IIC_TX_THRESHOLD; + iic_reg_ptr->IC_RX_TL = IIC_RX_THRESHOLD; + + dw_iic_enable(iic_reg_ptr); +} + +/** Check error for IIC master device */ +static int32_t dw_iic_mst_chkerr(DW_IIC_CTRL *iic_ctrl_ptr) +{ + uint32_t status; + int32_t ercd = IIC_ERR_NONE; + DW_IIC_REG *iic_reg_ptr = (DW_IIC_REG *)(iic_ctrl_ptr->dw_iic_regs); + + status = iic_reg_ptr->IC_RAW_INTR_STAT; + if (status & IC_INTR_STAT_TX_ABRT) { + status = iic_reg_ptr->IC_TX_ABRT_SOURCE; + if (status & IIC_MST_ABRT_LOST_BUS) { + ercd = IIC_ERR_LOST_BUS; + } else if (status & IIC_MST_ABRT_ADDR_NOACK) { + ercd = IIC_ERR_ADDR_NOACK; + } else if (status & IIC_MST_ABRT_DATA_NOACK) { + ercd = IIC_ERR_DATA_NOACK; + } else { + ercd = IIC_ERR_UNDEF; + } + status = iic_reg_ptr->IC_CLR_TX_ABRT; + } else { + if (status & IC_INTR_STAT_TX_OVER) { + iic_ctrl_ptr->iic_tx_over ++; + status = iic_reg_ptr->IC_CLR_TX_OVER; + } + if (status & (IC_INTR_STAT_RX_OVER|IC_INTR_STAT_RX_UNDER)) { + iic_ctrl_ptr->iic_rx_over ++; + status = iic_reg_ptr->IC_CLR_RX_OVER; + status = iic_reg_ptr->IC_CLR_RX_UNDER; + } + } + return ercd; +} + +/** Check error for IIC slave device */ +static int32_t dw_iic_slv_chkerr(DW_IIC_CTRL *iic_ctrl_ptr) +{ + uint32_t status; + int32_t ercd = IIC_ERR_NONE; + DW_IIC_REG *iic_reg_ptr = (DW_IIC_REG *)(iic_ctrl_ptr->dw_iic_regs); + + status = iic_reg_ptr->IC_RAW_INTR_STAT; + if (status & IC_INTR_STAT_TX_ABRT) { + status = iic_reg_ptr->IC_TX_ABRT_SOURCE; + if (status & IIC_SLV_ABRT_LOST_BUS) { + ercd = IIC_ERR_LOST_BUS; + } else if (status & IC_TX_ABRT_SLVFLUSH_TXFIFO) { + /* Flush tx fifo */ + status = iic_reg_ptr->IC_TX_ABRT_SOURCE; + } else { + ercd = IIC_ERR_UNDEF; + } + status = iic_reg_ptr->IC_CLR_TX_ABRT; + } else { + if (status & IC_INTR_STAT_TX_OVER) { + iic_ctrl_ptr->iic_tx_over ++; + status = iic_reg_ptr->IC_CLR_TX_OVER; + } + if (status & (IC_INTR_STAT_RX_OVER|IC_INTR_STAT_RX_UNDER)) { + iic_ctrl_ptr->iic_rx_over ++; + status = iic_reg_ptr->IC_CLR_RX_OVER; + status = iic_reg_ptr->IC_CLR_RX_UNDER; + } + } + return ercd; +} + +/** enable designware iic */ +static void dw_iic_enable_device(DEV_IIC_INFO *iic_info_ptr) +{ + DW_IIC_CTRL *iic_ctrl_ptr = (DW_IIC_CTRL *)(iic_info_ptr->iic_ctrl); + DW_IIC_REG *iic_reg_ptr = (DW_IIC_REG *)(iic_ctrl_ptr->dw_iic_regs); + + if ((iic_info_ptr->status & DEV_ENABLED) == 0) { + dw_iic_enable(iic_reg_ptr); + iic_info_ptr->status |= DEV_ENABLED; + } +} + +/** disable designware iic */ +static void dw_iic_disable_device(DEV_IIC_INFO *iic_info_ptr) +{ + DW_IIC_CTRL *iic_ctrl_ptr = (DW_IIC_CTRL *)(iic_info_ptr->iic_ctrl); + DW_IIC_REG *iic_reg_ptr = (DW_IIC_REG *)(iic_ctrl_ptr->dw_iic_regs); + uint32_t i; + + for (i=0; iIC_ENABLE_STATUS & IC_ENABLE_STATUS_IC_EN) == 0) { + break; + } + } + iic_info_ptr->status &= ~DEV_ENABLED; +} + +static void dw_iic_reset_device(DEV_IIC_INFO *iic_info_ptr) +{ + DW_IIC_CTRL *iic_ctrl_ptr = (DW_IIC_CTRL *)(iic_info_ptr->iic_ctrl); + DW_IIC_REG *iic_reg_ptr = (DW_IIC_REG *)(iic_ctrl_ptr->dw_iic_regs); + + dw_iic_disable_device(iic_info_ptr); + dw_iic_clear_interrupt_all(iic_reg_ptr); + iic_info_ptr->next_cond = IIC_MODE_STOP; + iic_info_ptr->cur_state = IIC_FREE; + iic_info_ptr->err_state = IIC_ERR_NONE; + iic_ctrl_ptr->iic_tx_over = 0; + iic_ctrl_ptr->iic_rx_over = 0; + dw_iic_enable_device(iic_info_ptr); +} + +/** Disable iic master interrupt for transmit or receive */ +static void dw_iic_mst_dis_cbr(DW_IIC_CTRL *iic_ctrl_ptr, uint32_t cbrtn) +{ + DW_IIC_REG *iic_reg_ptr = (DW_IIC_REG *)(iic_ctrl_ptr->dw_iic_regs); + + switch (cbrtn) { + case DW_IIC_RDY_SND: + dw_iic_mask_interrupt(iic_reg_ptr, IC_INT_MST_TX_ENABLE); + iic_ctrl_ptr->int_status &= ~DW_IIC_TXINT_ENABLE; + break; + case DW_IIC_RDY_RCV: + dw_iic_mask_interrupt(iic_reg_ptr, IC_INT_MST_RX_ENABLE); + iic_ctrl_ptr->int_status &= ~DW_IIC_RXINT_ENABLE; + break; + default: + break; + } +} + +/** Disable iic slave interrupt for transmit or receive */ +static void dw_iic_slv_dis_cbr(DW_IIC_CTRL *iic_ctrl_ptr, uint32_t cbrtn) +{ + DW_IIC_REG *iic_reg_ptr = (DW_IIC_REG *)(iic_ctrl_ptr->dw_iic_regs); + + switch (cbrtn) { + case DW_IIC_RDY_SND: + dw_iic_mask_interrupt(iic_reg_ptr, IC_INT_SLV_TX_ENABLE); + iic_ctrl_ptr->int_status &= ~DW_IIC_TXINT_ENABLE; + break; + case DW_IIC_RDY_RCV: + dw_iic_mask_interrupt(iic_reg_ptr, IC_INT_SLV_RX_ENABLE); + iic_ctrl_ptr->int_status &= ~DW_IIC_RXINT_ENABLE; + break; + default: + break; + } +} + +/** Enable iic master interrupt for transmit or receive */ +static void dw_iic_mst_ena_cbr(DW_IIC_CTRL *iic_ctrl_ptr, uint32_t cbrtn) +{ + DW_IIC_REG *iic_reg_ptr = (DW_IIC_REG *)(iic_ctrl_ptr->dw_iic_regs); + + switch (cbrtn) { + case DW_IIC_RDY_SND: + iic_ctrl_ptr->int_status |= DW_IIC_TXINT_ENABLE; + dw_iic_unmask_interrupt(iic_reg_ptr, IC_INT_MST_TX_ENABLE); + break; + case DW_IIC_RDY_RCV: + iic_ctrl_ptr->int_status |= DW_IIC_RXINT_ENABLE; + dw_iic_unmask_interrupt(iic_reg_ptr, IC_INT_MST_RX_ENABLE); + break; + default: + break; + } +} + +/** Enable iic slave interrupt for transmit or receive */ +static void dw_iic_slv_ena_cbr(DW_IIC_CTRL *iic_ctrl_ptr, uint32_t cbrtn) +{ + DW_IIC_REG *iic_reg_ptr = (DW_IIC_REG *)(iic_ctrl_ptr->dw_iic_regs); + + switch (cbrtn) { + case DW_IIC_RDY_SND: + iic_ctrl_ptr->int_status |= DW_IIC_TXINT_ENABLE; + dw_iic_unmask_interrupt(iic_reg_ptr, IC_INT_SLV_TX_ENABLE); + break; + case DW_IIC_RDY_RCV: + iic_ctrl_ptr->int_status |= DW_IIC_RXINT_ENABLE; + dw_iic_unmask_interrupt(iic_reg_ptr, IC_INT_SLV_RX_ENABLE); + break; + default: + break; + } +} + +/** + * \brief disable designware iic send or receive interrupt + * \param[in] DEV_IIC_INFO *iic_info_ptr + * \param[in] cbrtn control code of callback routine of send or receive + */ +static void dw_iic_dis_cbr(DEV_IIC_INFO *iic_info_ptr, uint32_t cbrtn) +{ + DW_IIC_CTRL *iic_ctrl_ptr = (DW_IIC_CTRL *)(iic_info_ptr->iic_ctrl); + + if (iic_info_ptr->mode == DEV_MASTER_MODE) { + dw_iic_mst_dis_cbr(iic_ctrl_ptr, cbrtn); + } else { + dw_iic_slv_dis_cbr(iic_ctrl_ptr, cbrtn); + } + + if (iic_ctrl_ptr->int_status & DW_IIC_GINT_ENABLE) { + if ((iic_ctrl_ptr->int_status & (DW_IIC_RXINT_ENABLE|DW_IIC_TXINT_ENABLE)) == 0) { + int_disable(iic_ctrl_ptr->intno); + iic_ctrl_ptr->int_status &= ~DW_IIC_GINT_ENABLE; + } + } +} + +/** + * \brief enable DesignWare IIC send or receive interrupt + * \param[in] DEV_IIC_INFO *iic_info_ptr + * \param[in] cbrtn control code of callback routine of send or receive + */ +static void dw_iic_ena_cbr(DEV_IIC_INFO *iic_info_ptr, uint32_t cbrtn) +{ + DW_IIC_CTRL *iic_ctrl_ptr = (DW_IIC_CTRL *)(iic_info_ptr->iic_ctrl); + + if (iic_info_ptr->mode == DEV_MASTER_MODE) { + dw_iic_mst_ena_cbr(iic_ctrl_ptr, cbrtn); + } else { + dw_iic_slv_ena_cbr(iic_ctrl_ptr, cbrtn); + } + + if ((iic_ctrl_ptr->int_status & DW_IIC_GINT_ENABLE) == 0) { + if (iic_ctrl_ptr->int_status & (DW_IIC_RXINT_ENABLE|DW_IIC_TXINT_ENABLE)) { + iic_ctrl_ptr->int_status |= DW_IIC_GINT_ENABLE; + int_enable(iic_ctrl_ptr->intno); + } + } +} + +/** + * \brief enable designware iic interrupt + * \param iic_info_ptr iic information structure pointer + */ +static void dw_iic_enable_interrupt(DEV_IIC_INFO *iic_info_ptr) +{ + DW_IIC_CTRL *iic_ctrl_ptr = (DW_IIC_CTRL *)(iic_info_ptr->iic_ctrl); + + int_handler_install(iic_ctrl_ptr->intno, iic_ctrl_ptr->dw_iic_int_handler); + iic_ctrl_ptr->int_status |= DW_IIC_GINT_ENABLE; + int_enable(iic_ctrl_ptr->intno); /** enable iic interrupt */ +} +/** + * \brief disable designware iic interrupt + * \param iic_info_ptr iic information structure pointer + */ +static void dw_iic_disable_interrupt(DEV_IIC_INFO *iic_info_ptr) +{ + DW_IIC_CTRL *iic_ctrl_ptr = (DW_IIC_CTRL *)(iic_info_ptr->iic_ctrl); + + /** disable iic send&receive interrupt after disable iic interrupt */ + dw_iic_dis_cbr(iic_info_ptr, DW_IIC_RDY_SND); + dw_iic_dis_cbr(iic_info_ptr, DW_IIC_RDY_RCV); + /* disable iic interrupt */ + int_disable(iic_ctrl_ptr->intno); + iic_ctrl_ptr->int_status &= ~(DW_IIC_GINT_ENABLE|DW_IIC_TXINT_ENABLE|DW_IIC_RXINT_ENABLE); +} + +/** abort current interrupt transmit transfer */ +static void dw_iic_abort_tx(DEV_IIC *iic_obj) +{ + DEV_IIC_INFO *iic_info_ptr = &(iic_obj->iic_info); + DW_IIC_CTRL *iic_ctrl_ptr = (DW_IIC_CTRL *)(iic_info_ptr->iic_ctrl); + + if (iic_ctrl_ptr->int_status & DW_IIC_TXINT_ENABLE) { + dw_iic_dis_cbr(iic_info_ptr, DW_IIC_RDY_SND); + iic_info_ptr->status |= DEV_IN_TX_ABRT; + if (iic_info_ptr->iic_cbs.tx_cb != NULL) { + iic_info_ptr->iic_cbs.tx_cb(iic_obj); + } + iic_info_ptr->status &= ~(DEV_IN_TX_ABRT); + } +} + +/** abort current interrupt receive transfer */ +static void dw_iic_abort_rx(DEV_IIC *iic_obj) +{ + DEV_IIC_INFO *iic_info_ptr = &(iic_obj->iic_info); + DW_IIC_CTRL *iic_ctrl_ptr = (DW_IIC_CTRL *)(iic_info_ptr->iic_ctrl); + + if (iic_ctrl_ptr->int_status & DW_IIC_RXINT_ENABLE) { + dw_iic_dis_cbr(iic_info_ptr, DW_IIC_RDY_RCV); + iic_info_ptr->status |= DEV_IN_RX_ABRT; + if (iic_info_ptr->iic_cbs.rx_cb != NULL) { + iic_info_ptr->iic_cbs.rx_cb(iic_obj); + } + iic_info_ptr->status &= ~(DEV_IN_RX_ABRT); + } +} + +/** Get available transmit fifo count */ +static int32_t dw_iic_get_txavail(DW_IIC_CTRL *iic_ctrl_ptr) +{ + int32_t tx_avail = 0; + DW_IIC_REG *iic_reg_ptr = (DW_IIC_REG *)(iic_ctrl_ptr->dw_iic_regs); + + if (iic_ctrl_ptr->tx_fifo_len <= 1) { + if (dw_iic_putready(iic_reg_ptr) == 1) { + tx_avail = 1; + } else { + tx_avail = 0; + } + } else { + tx_avail = iic_ctrl_ptr->tx_fifo_len - iic_reg_ptr->IC_TXFLR; + } + return tx_avail; +} + +/** Get available receive fifo count */ +static int32_t dw_iic_get_rxavail(DW_IIC_CTRL *iic_ctrl_ptr) +{ + int32_t rx_avail = 0; + DW_IIC_REG *iic_reg_ptr = (DW_IIC_REG *)(iic_ctrl_ptr->dw_iic_regs); + + if (iic_ctrl_ptr->rx_fifo_len <= 1) { + if (dw_iic_getready(iic_reg_ptr) == 1) { + rx_avail = 1; + } else { + rx_avail = 0; + } + } else { + rx_avail = iic_reg_ptr->IC_RXFLR; + } + return rx_avail; +} + +/** + * IIC Master device transmit 1 data, + * next_cond can be \ref IC_DATA_CMD_STOP, + * \ref IC_DATA_CMD_RESTART and ref IC_DATA_CMD_NONE + */ +static int32_t dw_iic_mst_write_data(DW_IIC_CTRL *iic_ctrl_ptr, uint32_t data, uint32_t next_cond) +{ + uint32_t i = 0; + int32_t ercd = IIC_ERR_NONE; + DW_IIC_REG *iic_reg_ptr = (DW_IIC_REG *)(iic_ctrl_ptr->dw_iic_regs); + + while (dw_iic_putready(iic_reg_ptr) == 0) { + if (i++ > iic_ctrl_ptr->retry_cnt) return IIC_ERR_TIMEOUT; + ercd = dw_iic_mst_chkerr(iic_ctrl_ptr); + if (ercd != IIC_ERR_NONE) return ercd; + } + dw_iic_putdata(iic_reg_ptr, data|IC_DATA_CMD_WRITE_REQ|next_cond); + + return ercd; +} + +/** IIC Slave device transmit 1 data */ +static int32_t dw_iic_slv_write_data(DW_IIC_CTRL *iic_ctrl_ptr, uint32_t data) +{ + uint32_t i = 0; + int32_t ercd = IIC_ERR_NONE; + uint32_t slv_state, temp; + uint32_t ready2send = 0; + DW_IIC_REG *iic_reg_ptr = (DW_IIC_REG *)(iic_ctrl_ptr->dw_iic_regs); + + for (i = 0; i < iic_ctrl_ptr->retry_cnt; i++) { + ercd = dw_iic_slv_chkerr(iic_ctrl_ptr); + if (ercd != IIC_ERR_NONE) return ercd; + slv_state = iic_reg_ptr->IC_RAW_INTR_STAT; + if (slv_state & IC_INTR_STAT_RD_REQ) { + if (dw_iic_putready(iic_reg_ptr)) { + temp = iic_reg_ptr->IC_CLR_RD_REQ; + ready2send = 1; + break; + } + } else if (slv_state & IC_INTR_STAT_RX_DONE) { /* Put RX Done before STOP */ + temp = iic_reg_ptr->IC_CLR_RX_DONE; + return IIC_ERR_MSTSTOP; + } else if (slv_state & IC_INTR_STAT_STOP_DET) { + temp = iic_reg_ptr->IC_CLR_STOP_DET; + return IIC_ERR_MSTSTOP; + } + } + if (ready2send) { + dw_iic_putdata(iic_reg_ptr, data|IC_DATA_CMD_WRITE_REQ); + } else { + ercd = IIC_ERR_TIMEOUT; + } + + return ercd; +} + +/** + * IIC Master device receive 1 data, + * next_cond can be \ref IC_DATA_CMD_STOP, + * \ref IC_DATA_CMD_RESTART and ref IC_DATA_CMD_NONE + */ +static int32_t dw_iic_mst_read_data(DW_IIC_CTRL *iic_ctrl_ptr, uint32_t *data, uint32_t next_cond) +{ + uint32_t i = 0; + int32_t ercd = IIC_ERR_NONE; + DW_IIC_REG *iic_reg_ptr = (DW_IIC_REG *)(iic_ctrl_ptr->dw_iic_regs); + + /* Issue a read request */ + while (dw_iic_putready(iic_reg_ptr) == 0) { + if (i++ > iic_ctrl_ptr->retry_cnt) return IIC_ERR_TIMEOUT; + ercd = dw_iic_mst_chkerr(iic_ctrl_ptr); + if (ercd != IIC_ERR_NONE) return ercd; + } + dw_iic_putdata(iic_reg_ptr, next_cond|IC_DATA_CMD_READ_REQ); + /* Wait to read data */ + i = 0; + while (dw_iic_getready(iic_reg_ptr) == 0) { + if (i++ > iic_ctrl_ptr->retry_cnt) return IIC_ERR_TIMEOUT; + ercd = dw_iic_mst_chkerr(iic_ctrl_ptr); + if (ercd != IIC_ERR_NONE) return ercd; + } + *data = dw_iic_getdata(iic_reg_ptr); + return ercd; +} + +/** IIC Slave device receive 1 data */ +static int32_t dw_iic_slv_read_data(DW_IIC_CTRL *iic_ctrl_ptr, uint32_t *data) +{ + uint32_t i = 0; + int32_t ercd = IIC_ERR_NONE; + uint32_t slv_state, temp; + uint32_t ready2read = 0; + DW_IIC_REG *iic_reg_ptr = (DW_IIC_REG *)(iic_ctrl_ptr->dw_iic_regs); + + for (i = 0; i < iic_ctrl_ptr->retry_cnt; i++) { + ercd = dw_iic_slv_chkerr(iic_ctrl_ptr); + if (ercd != IIC_ERR_NONE) return ercd; + slv_state = iic_reg_ptr->IC_RAW_INTR_STAT; + if (slv_state & IC_INTR_STAT_START_DET) { + temp = iic_reg_ptr->IC_CLR_START_DET; + } + if (slv_state & IC_INTR_STAT_RX_FULL) { + if (dw_iic_getready(iic_reg_ptr)) { + ready2read = 1; + break; + } + } else if (slv_state & IC_INTR_STAT_STOP_DET) { + temp = iic_reg_ptr->IC_CLR_STOP_DET; + return IIC_ERR_MSTSTOP; + } + } + if (ready2read) { + *data = dw_iic_getdata(iic_reg_ptr); + } else { + ercd = IIC_ERR_TIMEOUT; + } + + return ercd; +} + +/** IIC Master transmit called in interrupt */ +static void dw_iic_mst_int_write(DEV_IIC *iic_obj) +{ + DEV_IIC_INFO *iic_info_ptr = &(iic_obj->iic_info); + DW_IIC_CTRL *iic_ctrl_ptr = (DW_IIC_CTRL_PTR)(iic_info_ptr->iic_ctrl); + DW_IIC_REG *iic_reg_ptr = (DW_IIC_REG_PTR)(iic_ctrl_ptr->dw_iic_regs); + uint32_t iic_int_status; /** iic interrupt status */ + uint32_t last_cond, xmit_data, xmit_end = 0; + DEV_BUFFER *buf_ptr; + uint8_t *p_charbuf; + + if (iic_info_ptr->next_cond == IIC_MODE_STOP) { + last_cond = IC_DATA_CMD_STOP; + } else { + last_cond = IC_DATA_CMD_RESTART; + } + iic_int_status = (iic_reg_ptr->IC_INTR_STAT); + buf_ptr = &(iic_info_ptr->tx_buf); + p_charbuf = (uint8_t *)buf_ptr->buf; + if (p_charbuf) { + if (iic_int_status & IC_INTR_STAT_TX_EMPTY) { + xmit_end = 0; + while (dw_iic_putready(iic_reg_ptr)) { + xmit_data = (uint32_t)(p_charbuf[buf_ptr->ofs])|IC_DATA_CMD_WRITE_REQ; + if (buf_ptr->ofs == (buf_ptr->len-1)) { + xmit_end = 1; + xmit_data |= last_cond; + } else { + xmit_data |= IC_DATA_CMD_NONE; + } + buf_ptr->ofs ++; + dw_iic_putdata(iic_reg_ptr, xmit_data); + if (xmit_end) { + dw_iic_dis_cbr(iic_info_ptr, DW_IIC_RDY_SND); + iic_info_ptr->cur_state = IIC_FREE; + if (iic_info_ptr->iic_cbs.tx_cb) { + iic_info_ptr->iic_cbs.tx_cb(iic_obj); + } + /* clear the send buffer pointer */ + memset(buf_ptr, 0, sizeof(DEV_BUFFER)); + break; + } + } + } + if (iic_int_status & IC_INTR_STAT_TX_OVER) { + iic_ctrl_ptr->iic_tx_over ++; + } + if (iic_int_status & IC_INTR_STAT_TX_ABRT) { + iic_info_ptr->err_state = dw_iic_mst_chkerr(iic_ctrl_ptr); + if (iic_info_ptr->err_state != IIC_ERR_NONE) { + dw_iic_dis_cbr(iic_info_ptr, DW_IIC_RDY_SND); + iic_info_ptr->cur_state = IIC_FREE; + if (iic_info_ptr->iic_cbs.err_cb) { + iic_info_ptr->iic_cbs.err_cb(iic_obj); + } + /* clear the send buffer pointer */ + memset(buf_ptr, 0, sizeof(DEV_BUFFER)); + } + } + } else { + dw_iic_dis_cbr(iic_info_ptr, DW_IIC_RDY_SND); + iic_info_ptr->cur_state = IIC_FREE; + } + /* Clear Interrupt */ + iic_int_status = iic_reg_ptr->IC_CLR_INTR; +} + +/** IIC Master receive called in interrupt */ +static void dw_iic_mst_int_read(DEV_IIC *iic_obj) +{ + DEV_IIC_INFO *iic_info_ptr = &(iic_obj->iic_info); + DW_IIC_CTRL *iic_ctrl_ptr = (DW_IIC_CTRL_PTR)(iic_info_ptr->iic_ctrl); + DW_IIC_REG *iic_reg_ptr = (DW_IIC_REG_PTR)(iic_ctrl_ptr->dw_iic_regs); + uint32_t iic_int_status; /** iic interrupt status */ + uint32_t last_cond, xmit_data; + DEV_BUFFER *buf_ptr; + DW_IIC_BUFFER *dw_iic_rxbuf_ptr; + uint8_t *p_charbuf; + + if (iic_info_ptr->next_cond == IIC_MODE_STOP) { + last_cond = IC_DATA_CMD_STOP; + } else { + last_cond = IC_DATA_CMD_RESTART; + } + iic_int_status = (iic_reg_ptr->IC_INTR_STAT); + buf_ptr = &(iic_info_ptr->rx_buf); + p_charbuf = (uint8_t *)buf_ptr->buf; + if (p_charbuf) { + dw_iic_rxbuf_ptr = &(iic_ctrl_ptr->dw_iic_rxbuf); + if (iic_int_status & IC_INTR_STAT_TX_EMPTY) { + while (dw_iic_putready(iic_reg_ptr)) { + if (dw_iic_rxbuf_ptr->ofs >= dw_iic_rxbuf_ptr->len) { + dw_iic_mask_interrupt(iic_reg_ptr, IC_INTR_STAT_TX_EMPTY); + break; + } + xmit_data = IC_DATA_CMD_READ_REQ; + if (dw_iic_rxbuf_ptr->ofs == (dw_iic_rxbuf_ptr->len-1)) { + xmit_data |= last_cond; + } else { + xmit_data |= IC_DATA_CMD_NONE; + } + dw_iic_rxbuf_ptr->ofs ++; + dw_iic_putdata(iic_reg_ptr, xmit_data); + } + } + if (iic_int_status & IC_INTR_STAT_RX_FULL) { + while (dw_iic_getready(iic_reg_ptr)) { + p_charbuf[buf_ptr->ofs] = dw_iic_getdata(iic_reg_ptr); + buf_ptr->ofs ++; + if (buf_ptr->ofs >= buf_ptr->len) { + dw_iic_dis_cbr(iic_info_ptr, DW_IIC_RDY_RCV); + iic_info_ptr->cur_state = IIC_FREE; + if (iic_info_ptr->iic_cbs.rx_cb) { + iic_info_ptr->iic_cbs.rx_cb(iic_obj); + } + /* clear the send buffer pointer */ + memset(buf_ptr, 0, sizeof(DEV_BUFFER)); + dw_iic_rxbuf_ptr->ofs = 0; + dw_iic_rxbuf_ptr->len = 0; + break; + } + } + } + if (iic_int_status & (IC_INTR_STAT_RX_OVER|IC_INTR_STAT_RX_UNDER)) { + iic_ctrl_ptr->iic_rx_over ++; + } + if (iic_int_status & IC_INTR_STAT_TX_ABRT) { + iic_info_ptr->err_state = dw_iic_mst_chkerr(iic_ctrl_ptr); + if (iic_info_ptr->err_state != IIC_ERR_NONE) { + dw_iic_dis_cbr(iic_info_ptr, DW_IIC_RDY_RCV); + iic_info_ptr->cur_state = IIC_FREE; + if (iic_info_ptr->iic_cbs.err_cb) { + iic_info_ptr->iic_cbs.err_cb(iic_obj); + } + /* clear the send buffer pointer */ + memset(buf_ptr, 0, sizeof(DEV_BUFFER)); + dw_iic_rxbuf_ptr->ofs = 0; + dw_iic_rxbuf_ptr->len = 0; + } + } + } else { + dw_iic_dis_cbr(iic_info_ptr, DW_IIC_RDY_RCV); + iic_info_ptr->cur_state = IIC_FREE; + } + /* Clear Interrupt */ + iic_int_status = iic_reg_ptr->IC_CLR_INTR; +} + +/** IIC Slave transmit called in interrupt */ +static void dw_iic_slv_int_process(DEV_IIC *iic_obj) +{ + DEV_IIC_INFO *iic_info_ptr = &(iic_obj->iic_info); + DW_IIC_CTRL *iic_ctrl_ptr = (DW_IIC_CTRL_PTR)(iic_info_ptr->iic_ctrl); + DW_IIC_REG *iic_reg_ptr = (DW_IIC_REG_PTR)(iic_ctrl_ptr->dw_iic_regs); + uint32_t iic_int_status; /** iic interrupt status */ + + iic_int_status = (iic_reg_ptr->IC_INTR_STAT); + if (iic_int_status & IC_INTR_STAT_RD_REQ) { /* Read request from master */ + if (iic_info_ptr->iic_cbs.tx_cb) { + iic_info_ptr->iic_cbs.tx_cb(iic_obj); + } else { /* When tx callback function is not set disable this tx int for slave */ + dw_iic_dis_cbr(iic_info_ptr, DW_IIC_RDY_SND); + } + } + if (iic_int_status & IC_INTR_STAT_RX_FULL) { /* Write request from master */ + if (iic_info_ptr->iic_cbs.rx_cb) { + iic_info_ptr->iic_cbs.rx_cb(iic_obj); + } else { /* When rx callback function is not set disable this rx int for slave */ + dw_iic_dis_cbr(iic_info_ptr, DW_IIC_RDY_RCV); + } + } + if (iic_int_status & IC_INTR_STAT_TX_OVER) { + iic_ctrl_ptr->iic_tx_over ++; + } + if (iic_int_status & (IC_INTR_STAT_RX_OVER|IC_INTR_STAT_RX_UNDER)) { + iic_ctrl_ptr->iic_rx_over ++; + } + if (iic_int_status & IC_INTR_STAT_TX_ABRT) { + iic_info_ptr->err_state = dw_iic_slv_chkerr(iic_ctrl_ptr); + if (iic_info_ptr->err_state != IIC_ERR_NONE) { + if (iic_info_ptr->iic_cbs.err_cb) { + iic_info_ptr->iic_cbs.err_cb(iic_obj); + } + } + } + /* Clear Interrupt */ + iic_int_status = iic_reg_ptr->IC_CLR_INTR; +} + +/** @} end of group DEVICE_DW_IIC_STATIC */ + +/** + * \defgroup DEVICE_DW_IIC_IMPLEMENT DesignWare IIC Driver Function API Implement + * \ingroup DEVICE_DW_IIC + * \brief implement device hal iic api with DesignWare IIC + * @{ + */ + +/** + * \brief open a designware iic device + * \param[in] iic_obj iic device object pointer + * \param[in] mode iic working mode (master or slave) + * \param[in] param When mode is \ref DEV_MASTER_MODE, param stands for \ref dev_iic_info::speed_mode "speed mode", + * when mode is \ref DEV_SLAVE_MODE, param stands for \ref dev_iic_info::slv_addr "slave device 7bit address" + * \retval E_OK Open successfully without any issues + * \retval E_OPNED If device was opened before with different parameters, + * then just increase the \ref dev_iic_info::opn_cnt "opn_cnt" and return \ref E_OPNED + * \retval E_OBJ Device object is not valid + * \retval E_SYS Device is opened for different mode before, if you want to open it with different mode, you need to fully close it first. + * \retval E_PAR Parameter is not valid + * \retval E_NOSPT Open settings are not supported + */ +int32_t dw_iic_open (DEV_IIC *iic_obj, uint32_t mode, uint32_t param) +{ + int32_t ercd = E_OK; + uint32_t support_modes; + uint32_t param2check; + DEV_IIC_INFO *iic_info_ptr = &(iic_obj->iic_info); + + /* START ERROR CHECK */ + VALID_CHK_IIC_INFO_OBJECT(iic_info_ptr); + DW_IIC_CHECK_EXP((mode==DEV_MASTER_MODE)||(mode==DEV_SLAVE_MODE), E_PAR); + if (mode == DEV_MASTER_MODE) { + DW_IIC_CHECK_EXP((param>=IIC_SPEED_STANDARD) && (param<=IIC_SPEED_ULTRA), E_PAR); + } + /* END OF ERROR CHECK */ + + DW_IIC_CTRL *iic_ctrl_ptr = (DW_IIC_CTRL *)(iic_info_ptr->iic_ctrl); + + /* Check supported modes, master or slave */ + support_modes = iic_ctrl_ptr->support_modes; + DW_IIC_CHECK_EXP( (((support_modes)&DW_IIC_MASTER_SUPPORTED)&&(mode == DEV_MASTER_MODE)) || \ + (((support_modes)&DW_IIC_SLAVE_SUPPORTED)&&(mode == DEV_SLAVE_MODE)), E_NOSPT); + + /** Check opened before use case */ + if (iic_info_ptr->opn_cnt > 0) { + if (mode != iic_info_ptr->mode) { + /* current working mode is different from passing mode */ + return E_SYS; + } + if (mode == DEV_MASTER_MODE) { /* param is speed_mode when as master */ + param2check = iic_info_ptr->speed_mode; + } else { /* param is slv_addr when as slave */ + param2check = iic_info_ptr->slv_addr; + } + iic_info_ptr->opn_cnt ++; + if (param != param2check) { /* open with different speed mode */ + return E_OPNED; + } else { + return E_OK; + } + } + /* auto increase open count */ + iic_info_ptr->opn_cnt ++; + + iic_info_ptr->mode = mode; + if (iic_info_ptr->addr_mode == IIC_7BIT_ADDRESS) { + iic_info_ptr->tar_addr &= IIC_7BIT_ADDRESS_MASK; + iic_info_ptr->slv_addr &= IIC_7BIT_ADDRESS_MASK; + } else { + iic_info_ptr->addr_mode = IIC_10BIT_ADDRESS; + iic_info_ptr->tar_addr &= IIC_10BIT_ADDRESS_MASK; + iic_info_ptr->slv_addr &= IIC_10BIT_ADDRESS_MASK; + } + +/* Do FIFO Length get before init */ +#if DW_IIC_CALC_FIFO_LEN_ENABLE + iic_ctrl_ptr->tx_fifo_len = dw_iic_get_txfifo_len(iic_ctrl_ptr->dw_iic_regs); + iic_ctrl_ptr->rx_fifo_len = dw_iic_get_rxfifo_len(iic_ctrl_ptr->dw_iic_regs); +#endif + + /* Disable device before init it */ + dw_iic_disable_device(iic_info_ptr); + + if (mode == DEV_MASTER_MODE) { + iic_info_ptr->speed_mode = param; + dw_iic_master_init(iic_ctrl_ptr, param, iic_info_ptr->addr_mode, iic_info_ptr->tar_addr); + } else { + iic_info_ptr->slv_addr = param; + dw_iic_slave_init(iic_ctrl_ptr, iic_info_ptr->addr_mode, param); + } + iic_info_ptr->status = DEV_ENABLED; + iic_info_ptr->cur_state = IIC_FREE; + iic_info_ptr->err_state = IIC_ERR_NONE; + iic_info_ptr->next_cond = IIC_MODE_STOP; + iic_info_ptr->extra = NULL; + + iic_ctrl_ptr->iic_tx_over = 0; + iic_ctrl_ptr->iic_rx_over = 0; + iic_ctrl_ptr->int_status = 0; + memset(&(iic_ctrl_ptr->dw_iic_rxbuf), 0, sizeof(DW_IIC_BUFFER)); + iic_ctrl_ptr->dw_iic_rxbuf.buf = &(iic_info_ptr->rx_buf); + /** install iic interrupt into system */ + dw_iic_disable_interrupt(iic_info_ptr); + int_handler_install(iic_ctrl_ptr->intno, iic_ctrl_ptr->dw_iic_int_handler); + memset(&(iic_info_ptr->tx_buf), 0, sizeof(DEV_BUFFER)); + memset(&(iic_info_ptr->rx_buf), 0, sizeof(DEV_BUFFER)); + memset(&(iic_info_ptr->iic_cbs), 0, sizeof(DEV_IIC_CBS)); + +error_exit: + return ercd; +} + +/** + * \brief Close a DesignWare IIC device + * \param[in] iic_obj iic device object pointer + * \retval E_OK Close successfully without any issues(including secenary that device is already closed) + * \retval E_OPNED Device is still opened, the device \ref dev_iic_info::opn_cnt "opn_cnt" decreased by 1 + * \retval E_OBJ Device object is not valid + */ +int32_t dw_iic_close (DEV_IIC *iic_obj) +{ + int32_t ercd = E_OK; + DEV_IIC_INFO *iic_info_ptr = &(iic_obj->iic_info); + + /* START ERROR CHECK */ + VALID_CHK_IIC_INFO_OBJECT(iic_info_ptr); + DW_IIC_CHECK_EXP(iic_info_ptr->opn_cnt > 0, E_OK); + /* END OF ERROR CHECK */ + + iic_info_ptr->opn_cnt --; + if (iic_info_ptr->opn_cnt == 0) { + dw_iic_disable_interrupt(iic_info_ptr); + dw_iic_abort_tx(iic_obj); + dw_iic_abort_rx(iic_obj); + memset(&(iic_info_ptr->tx_buf), 0, sizeof(DEV_BUFFER)); + memset(&(iic_info_ptr->rx_buf), 0, sizeof(DEV_BUFFER)); + memset(&(iic_info_ptr->iic_cbs), 0, sizeof(DEV_IIC_CBS)); + dw_iic_disable_device(iic_info_ptr); + iic_info_ptr->status = DEV_DISABLED; + iic_info_ptr->next_cond = IIC_MODE_STOP; + iic_info_ptr->extra = NULL; + } else { + ercd = E_OPNED; + } + +error_exit: + return ercd; +} + +/** + * \brief Control iic by ctrl command + * \param[in] iic_obj iic device object pointer + * \param[in] ctrl_cmd \ref DEVICE_HAL_IIC_CTRLCMD "control command", to change or get some thing related to iic + * \param[in,out] param parameters that maybe argument of the command, + * or return values of the command, must not be NULL + * \retval E_OK Control device successfully + * \retval E_CLSED Device is not opened + * \retval E_OBJ Device object is not valid or not exists + * \retval E_PAR Parameter is not valid for current control command + * \retval E_SYS Control device failed, due to hardware issues, such as device is disabled + * \retval E_CTX Control device failed, due to different reasons like in transfer state + * \retval E_NOSPT Control command is not supported or not valid + */ +int32_t dw_iic_control (DEV_IIC *iic_obj, uint32_t ctrl_cmd, void *param) +{ + int32_t ercd = E_OK; + DEV_IIC_INFO *iic_info_ptr = &(iic_obj->iic_info); + + /* START ERROR CHECK */ + VALID_CHK_IIC_INFO_OBJECT(iic_info_ptr); + DW_IIC_CHECK_EXP(iic_info_ptr->opn_cnt > 0, E_CLSED); + /* END OF ERROR CHECK */ + + uint32_t val32; /** to receive unsigned int value */ + DEV_BUFFER *devbuf; + + DW_IIC_CTRL *iic_ctrl_ptr = (DW_IIC_CTRL *)(iic_info_ptr->iic_ctrl); + DW_IIC_REG *iic_reg_ptr = (DW_IIC_REG *)(iic_ctrl_ptr->dw_iic_regs); + + /* check whether current device is disabled */ + if ((iic_info_ptr->status & DEV_ENABLED) == 0) { + /** When device is disabled, + * only IIC_CMD_ENA_DEV, IIC_CMD_DIS_DEV, IIC_CMD_GET_STATUS, IIC_CMD_RESET + * are available, other commands will return E_SYS + */ + if ((ctrl_cmd != IIC_CMD_ENA_DEV) && \ + (ctrl_cmd != IIC_CMD_DIS_DEV) && \ + (ctrl_cmd != IIC_CMD_GET_STATUS) && \ + (ctrl_cmd != IIC_CMD_RESET) ) { + return E_SYS; + } + } + + switch (ctrl_cmd) { + /* Commmon commands for both master and slave mode */ + case IIC_CMD_GET_STATUS: + DW_IIC_CHECK_EXP((param!=NULL) && CHECK_ALIGN_4BYTES(param), E_PAR); + *((int32_t *)param) = iic_info_ptr->status; + break; + case IIC_CMD_ENA_DEV: + dw_iic_enable_device(iic_info_ptr); + break; + case IIC_CMD_DIS_DEV: + dw_iic_disable_device(iic_info_ptr); + break; + case IIC_CMD_RESET: + dw_iic_reset_device(iic_info_ptr); + break; + case IIC_CMD_FLUSH_TX: + dw_iic_flush_tx(iic_reg_ptr); + break; + case IIC_CMD_FLUSH_RX: + dw_iic_flush_rx(iic_reg_ptr); + break; + case IIC_CMD_SET_ADDR_MODE: + val32 = (uint32_t)param; + DW_IIC_CHECK_EXP((val32==IIC_7BIT_ADDRESS) || (val32==IIC_10BIT_ADDRESS), E_PAR); + if (iic_info_ptr->mode == DEV_MASTER_MODE) { + dw_iic_set_mstaddr_mode(iic_reg_ptr, val32); + } else { + dw_iic_set_slvaddr_mode(iic_reg_ptr, val32); + } + iic_info_ptr->addr_mode = val32; + break; + case IIC_CMD_GET_RXAVAIL: + DW_IIC_CHECK_EXP((param!=NULL) && CHECK_ALIGN_4BYTES(param), E_PAR); + *((int32_t *)param) = dw_iic_get_rxavail(iic_ctrl_ptr); + break; + case IIC_CMD_GET_TXAVAIL: + DW_IIC_CHECK_EXP((param!=NULL) && CHECK_ALIGN_4BYTES(param), E_PAR); + *((int32_t *)param) = dw_iic_get_txavail(iic_ctrl_ptr); + break; + case IIC_CMD_SET_TXCB: + DW_IIC_CHECK_EXP(CHECK_ALIGN_4BYTES(param), E_PAR); + iic_info_ptr->iic_cbs.tx_cb = param; + break; + case IIC_CMD_SET_RXCB: + DW_IIC_CHECK_EXP(CHECK_ALIGN_4BYTES(param), E_PAR); + iic_info_ptr->iic_cbs.rx_cb = param; + break; + case IIC_CMD_SET_ERRCB: + DW_IIC_CHECK_EXP(CHECK_ALIGN_4BYTES(param), E_PAR); + iic_info_ptr->iic_cbs.err_cb = param; + break; + case IIC_CMD_ABORT_TX: + dw_iic_abort_tx(iic_obj); + if ((iic_info_ptr->mode == DEV_MASTER_MODE) \ + && (iic_info_ptr->cur_state == IIC_IN_TX)) { + iic_info_ptr->cur_state = IIC_FREE; + } + break; + case IIC_CMD_ABORT_RX: + dw_iic_abort_rx(iic_obj); + if ((iic_info_ptr->mode == DEV_MASTER_MODE) \ + && (iic_info_ptr->cur_state == IIC_IN_RX)) { + iic_info_ptr->cur_state = IIC_FREE; + } + break; + case IIC_CMD_SET_TXINT: + if (iic_info_ptr->mode == DEV_MASTER_MODE) { + DW_IIC_CHECK_EXP(iic_info_ptr->cur_state != IIC_IN_RX, E_CTX); + } + val32 = (uint32_t)param; + if (val32 == 0) { + dw_iic_dis_cbr(iic_info_ptr, DW_IIC_RDY_SND); + iic_info_ptr->cur_state = IIC_FREE; + } else { + iic_info_ptr->cur_state = IIC_IN_TX; + dw_iic_ena_cbr(iic_info_ptr, DW_IIC_RDY_SND); + } + break; + case IIC_CMD_SET_RXINT: + if (iic_info_ptr->mode == DEV_MASTER_MODE) { + DW_IIC_CHECK_EXP(iic_info_ptr->cur_state != IIC_IN_TX, E_CTX); + } + val32 = (uint32_t)param; + if (val32 == 0) { + iic_info_ptr->cur_state = IIC_FREE; + dw_iic_dis_cbr(iic_info_ptr, DW_IIC_RDY_RCV); + } else { + iic_info_ptr->cur_state = IIC_IN_RX; + dw_iic_ena_cbr(iic_info_ptr, DW_IIC_RDY_RCV); + } + break; + case IIC_CMD_SET_TXINT_BUF: + if (iic_info_ptr->mode == DEV_MASTER_MODE) { + DW_IIC_CHECK_EXP(iic_info_ptr->cur_state != IIC_IN_TX, E_CTX); + } + DW_IIC_CHECK_EXP(CHECK_ALIGN_4BYTES(param), E_PAR); + if (param != NULL) { + devbuf = (DEV_BUFFER *)param; + iic_info_ptr->tx_buf = *devbuf; + iic_info_ptr->tx_buf.ofs = 0; + } else { + iic_info_ptr->tx_buf.buf = NULL; + iic_info_ptr->tx_buf.len = 0; + iic_info_ptr->tx_buf.ofs = 0; + } + break; + case IIC_CMD_SET_RXINT_BUF: + if (iic_info_ptr->mode == DEV_MASTER_MODE) { + DW_IIC_CHECK_EXP(iic_info_ptr->cur_state != IIC_IN_RX, E_CTX); + } + DW_IIC_CHECK_EXP(CHECK_ALIGN_4BYTES(param), E_PAR); + if (param != NULL) { + devbuf = (DEV_BUFFER *)param; + iic_info_ptr->rx_buf = *devbuf; + iic_info_ptr->rx_buf.ofs = 0; + iic_ctrl_ptr->dw_iic_rxbuf.ofs = 0; + iic_ctrl_ptr->dw_iic_rxbuf.len = devbuf->len; + } else { + iic_info_ptr->rx_buf.buf = NULL; + iic_info_ptr->rx_buf.len = 0; + iic_info_ptr->rx_buf.ofs = 0; + iic_ctrl_ptr->dw_iic_rxbuf.ofs = 0; + iic_ctrl_ptr->dw_iic_rxbuf.len = 0; + } + break; + + /* Master mode only commands */ + case IIC_CMD_MST_SET_SPEED_MODE: + DW_IIC_CHECK_EXP(iic_info_ptr->mode == DEV_MASTER_MODE, E_NOSPT); + val32 = (uint32_t)param; + DW_IIC_CHECK_EXP((val32>=IIC_SPEED_STANDARD) && (val32<=IIC_SPEED_ULTRA), E_PAR); + dw_iic_set_speedmode(iic_reg_ptr, val32); + iic_info_ptr->speed_mode = val32; + break; + case IIC_CMD_MST_SET_TAR_ADDR: + DW_IIC_CHECK_EXP(iic_info_ptr->mode == DEV_MASTER_MODE, E_NOSPT); + if (iic_info_ptr->addr_mode == IIC_7BIT_ADDRESS) { + val32 = ((uint32_t)param) & IIC_7BIT_ADDRESS_MASK; + } else { + val32 = ((uint32_t)param) & IIC_10BIT_ADDRESS_MASK; + } + if (val32 != iic_info_ptr->tar_addr) { + dw_iic_set_taraddr(iic_reg_ptr, val32); + iic_info_ptr->tar_addr = val32; + } + break; + case IIC_CMD_MST_SET_NEXT_COND: + DW_IIC_CHECK_EXP(iic_info_ptr->mode == DEV_MASTER_MODE, E_NOSPT); + val32 = (uint32_t)param; + DW_IIC_CHECK_EXP((val32==IIC_MODE_STOP) || (val32==IIC_MODE_RESTART), E_PAR); + iic_info_ptr->next_cond = (uint32_t)param; + break; + + /* Slave mode only commands */ + case IIC_CMD_SLV_SET_SLV_ADDR: + DW_IIC_CHECK_EXP(iic_info_ptr->mode == DEV_SLAVE_MODE, E_NOSPT); + if (iic_info_ptr->addr_mode == IIC_7BIT_ADDRESS) { + val32 = ((uint32_t)param) & IIC_7BIT_ADDRESS_MASK; + } else { + val32 = ((uint32_t)param) & IIC_10BIT_ADDRESS_MASK; + } + dw_iic_set_slvaddr(iic_reg_ptr, val32); + iic_info_ptr->slv_addr = val32; + break; + case IIC_CMD_SLV_GET_SLV_STATE: + DW_IIC_CHECK_EXP(iic_info_ptr->mode == DEV_SLAVE_MODE, E_NOSPT); + DW_IIC_CHECK_EXP((param!=NULL) && CHECK_ALIGN_4BYTES(param), E_PAR); + *((uint32_t *)param) = dw_iic_get_slv_state(iic_reg_ptr); + break; + + default: + ercd = E_NOSPT; + break; + } + +error_exit: + return ercd; +} + +/** + * \brief poll transmit data through DesignWare IIC as master or slave + * \param[in] iic_obj iic device object pointer + * \param[in] data data that need to send (data must be uint8_t type) + * \param[in] len data length need to send + * \retval >0 Byte count that was successfully sent for poll method, + * it might can't send that much due to \ref \ref dev_iic_info::err_state "different error state". + * \retval E_OBJ Device object is not valid or not exists + * \retval E_PAR Parameter is not valid + * \retval E_CTX Device is still in transfer state + * \retval E_SYS Can't write data to hardware due to hardware issues, such as device is disabled + */ +int32_t dw_iic_write (DEV_IIC *iic_obj, const void *data, uint32_t len) +{ + int32_t ercd = E_OK; + DEV_IIC_INFO *iic_info_ptr = &(iic_obj->iic_info); + + /* START ERROR CHECK */ + VALID_CHK_IIC_INFO_OBJECT(iic_info_ptr); + DW_IIC_CHECK_EXP(iic_info_ptr->opn_cnt > 0, E_CLSED); + DW_IIC_CHECK_EXP(iic_info_ptr->status & DEV_ENABLED, E_SYS); + DW_IIC_CHECK_EXP(data!=NULL, E_PAR); + DW_IIC_CHECK_EXP(len>0, E_PAR); + /* END OF ERROR CHECK */ + + int32_t i = 0; + uint32_t last_cond = 0; /* Last data for transmit, STOP or RESTART */ + int32_t error_state = IIC_ERR_NONE; + const uint8_t *p_charbuf = (const uint8_t *)data; + + DW_IIC_CTRL *iic_ctrl_ptr = (DW_IIC_CTRL_PTR)(iic_info_ptr->iic_ctrl); + + if (iic_info_ptr->mode == DEV_MASTER_MODE) { /* Master mode transmit data */ + if (iic_info_ptr->next_cond == IIC_MODE_STOP) { + last_cond = IC_DATA_CMD_STOP; + } else { + last_cond = IC_DATA_CMD_RESTART; + } + + /* Try to transmit 0 -> (len-1) data */ + len = len - 1; /* Last data write differently */ + while (i < len) { + error_state = dw_iic_mst_write_data(iic_ctrl_ptr, (uint32_t)(p_charbuf[i]), IC_DATA_CMD_NONE); + if (error_state != IIC_ERR_NONE) { + break; + } + i ++; + } + /* Try to transmit the last data with STOP or RESTART condition */ + if (error_state == IIC_ERR_NONE) { + error_state = dw_iic_mst_write_data(iic_ctrl_ptr, (uint32_t)(p_charbuf[len]), last_cond); + if (error_state == IIC_ERR_NONE) { + i = i + 1; /* Add last data into send count */ + } + } + } else { /* Slave mode transmit data */ + while (i < len) { + error_state = dw_iic_slv_write_data(iic_ctrl_ptr, (uint32_t)(p_charbuf[i])); + if (error_state != IIC_ERR_NONE) { + break; + } + i ++; + } + } + iic_info_ptr->err_state = error_state; + ercd = i; + +error_exit: + return ercd; +} + +/** + * \brief read data through DesignWare IIC + * \param[in] iic_obj iic device object pointer + * \param[out] data data that need to read (data must be uint8_t type) + * \param[in] len data count need to read + * \retval >0 Byte count that was successfully received for poll method, + * it might can't send that much due to \ref \ref dev_iic_info::err_state "different error state". + * \retval E_OBJ Device object is not valid or not exists + * \retval E_CTX Device is still in transfer state + * \retval E_PAR Parameter is not valid + * \retval E_SYS Can't receive data from hardware due to hardware issues, such as device is disabled + */ +int32_t dw_iic_read (DEV_IIC *iic_obj, void *data, uint32_t len) +{ + int32_t ercd = E_OK; + DEV_IIC_INFO *iic_info_ptr = &(iic_obj->iic_info); + + /* START ERROR CHECK */ + VALID_CHK_IIC_INFO_OBJECT(iic_info_ptr); + DW_IIC_CHECK_EXP(iic_info_ptr->opn_cnt > 0, E_CLSED); + DW_IIC_CHECK_EXP(iic_info_ptr->status & DEV_ENABLED, E_SYS); + DW_IIC_CHECK_EXP(data!=NULL, E_PAR); + DW_IIC_CHECK_EXP(len>0, E_PAR); + /* END OF ERROR CHECK */ + + int32_t i = 0; + uint32_t last_cond = 0; /* Last data for receive, STOP or RESTART */ + uint32_t val32 = 0; + int32_t error_state = IIC_ERR_NONE; + uint8_t *p_charbuf = (uint8_t *)data; + + DW_IIC_CTRL *iic_ctrl_ptr = (DW_IIC_CTRL_PTR)(iic_info_ptr->iic_ctrl); + + if (iic_info_ptr->mode == DEV_MASTER_MODE) { /* Master mode receive data */ + if (iic_info_ptr->next_cond == IIC_MODE_STOP) { + last_cond = IC_DATA_CMD_STOP; + } else { + last_cond = IC_DATA_CMD_RESTART; + } + + /* Try to receive 0 -> (len-1) data */ + len = len - 1; /* Last data write differently */ + while (i < len) { + error_state = dw_iic_mst_read_data(iic_ctrl_ptr, &val32, IC_DATA_CMD_NONE); + if (error_state != IIC_ERR_NONE) { + break; + } else { + p_charbuf[i] = (uint8_t)val32; + } + i ++; + } + /* Try to receive the last data with STOP or RESTART condition */ + if (error_state == IIC_ERR_NONE) { + error_state = dw_iic_mst_read_data(iic_ctrl_ptr, &val32, last_cond); + if (error_state == IIC_ERR_NONE) { + p_charbuf[len] = (uint8_t)val32; + i = i + 1; /* Add last data into send count */ + } + } + } else { /* Slave mode receive data */ + while (i < len) { + error_state = dw_iic_slv_read_data(iic_ctrl_ptr, &val32); + if (error_state != IIC_ERR_NONE) { + break; + } else { + p_charbuf[i] = (uint8_t)val32; + } + i ++; + } + } + iic_info_ptr->err_state = error_state; + ercd = i; + +error_exit: + return ercd; +} + +/** + * \brief DesignWare IIC interrupt processing routine + * \param[in] iic_info_ptr DEV_IIC *iic_obj + * \param[in] ptr extra information + */ +void dw_iic_isr(DEV_IIC *iic_obj, void *ptr) +{ + int32_t ercd = E_OK; + DEV_IIC_INFO *iic_info_ptr = &(iic_obj->iic_info); + + /* START ERROR CHECK */ + VALID_CHK_IIC_INFO_OBJECT(iic_info_ptr); + /* END OF ERROR CHECK */ + + if (iic_info_ptr->mode == DEV_MASTER_MODE) { + if (iic_info_ptr->cur_state == IIC_IN_TX) { + dw_iic_mst_int_write(iic_obj); + } else { + dw_iic_mst_int_read(iic_obj); + } + } else { + dw_iic_slv_int_process(iic_obj); + } + +error_exit: + return; +} +/** @} end of group DEVICE_DW_IIC_IMPLEMENT */ diff --git a/hw/mcu/arc/src/ext/sdk/device/designware/iic/dw_iic.h b/hw/mcu/arc/src/ext/sdk/device/designware/iic/dw_iic.h new file mode 100644 index 000000000..55c551a67 --- /dev/null +++ b/hw/mcu/arc/src/ext/sdk/device/designware/iic/dw_iic.h @@ -0,0 +1,242 @@ +/* ------------------------------------------ + * Copyright (c) 2017, Synopsys, Inc. All rights reserved. + + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + + * 1) Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + + * 2) 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. + + * 3) Neither the name of the Synopsys, Inc., nor the names of its contributors may + * be used to endorse or promote products derived from this software without + * specific prior written permission. + + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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. + * + * \version 2017.03 + * \date 2014-06-30 + * \author Huaqi Fang(Huaqi.Fang@synopsys.com) +--------------------------------------------- */ + +/** + * \file + * \brief designware iic driver header file + * \ingroup DEVICE_DW_IIC + */ + +#ifndef _DW_IIC_H_ +#define _DW_IIC_H_ + +#include "device/device_hal/inc/dev_iic.h" + +#include "inc/arc/arc_exception.h" + + +/** + * If this header file is included, + * will indicate that this designware iic device + * is used + */ +#define DEVICE_USE_DESIGNWARE_IIC + +/** + * \defgroup DEVICE_DW_IIC_INFO DesignWare IIC Related Information + * \ingroup DEVICE_DW_IIC + * \brief Defines some macros of DesignWare IIC need. + * \details macros like, iic number + * @{ + */ +#define DW_IIC_MASTER_SUPPORTED (0x1) /*!< Support Designware IIC Master Mode */ +#define DW_IIC_SLAVE_SUPPORTED (0x2) /*!< Support Designware IIC Slave Mode */ +/*!< Support Designware IIC Both Master and Slave Mode */ +#define DW_IIC_BOTH_SUPPORTED (DW_IIC_MASTER_SUPPORTED|DW_IIC_SLAVE_SUPPORTED) +/** @} */ + +/** + * \defgroup DEVICE_DW_IIC_REGSTRUCT DesignWare IIC Register Structure + * \ingroup DEVICE_DW_IIC + * \brief contains definitions of DesignWare IIC register structure. + * \details detailed description of DesignWare IIC register information + * @{ + */ +/** + * \brief DesignWare IIC register structure + * \details Detailed struct description of DesignWare IIC + * block register information, implementation of dev_iic_info::iic_regs + */ +typedef volatile struct dw_iic_reg { + uint32_t IC_CON; /*!< (0x00) : IIC control */ + uint32_t IC_TAR; /*!< (0x04) : IIC target address */ + uint32_t IC_SAR; /*!< (0x08) : IIC slave address */ + uint32_t IC_HS_MADDR; /*!< (0x0c) : IIC HS Master Mode Code address */ + uint32_t IC_DATA_CMD; /*!< (0x10) : IIC Rx/Tx Data Buffer and Command */ + uint32_t IC_SS_SCL_HCNT; /*!< (0x14) : Standard Speed IIC clock SCL High Count */ + uint32_t IC_SS_SCL_LCNT; /*!< (0x18) : Standard Speed IIC clock SCL Low Count */ + uint32_t IC_FS_SCL_HCNT; /*!< (0x1c) : Fast Speed IIC clock SCL Low Count */ + uint32_t IC_FS_SCL_LCNT; /*!< (0x20) : Fast Speed IIC clock SCL Low Count */ + uint32_t IC_HS_SCL_HCNT; /*!< (0x24) : High Speed IIC clock SCL Low Count */ + uint32_t IC_HS_SCL_LCNT; /*!< (0x28) : High Speed IIC clock SCL Low Count */ + uint32_t IC_INTR_STAT; /*!< (0x2c) : IIC Interrupt Status */ + uint32_t IC_INTR_MASK; /*!< (0x30) : IIC Interrupt Mask */ + uint32_t IC_RAW_INTR_STAT; /*!< (0x34) : IIC Raw Interrupt Status */ + uint32_t IC_RX_TL; /*!< (0x38) : IIC Receive FIFO Threshold */ + uint32_t IC_TX_TL; /*!< (0x3c) : IIC Transmit FIFO Threshold */ + uint32_t IC_CLR_INTR; /*!< (0x40) : Clear combined and Individual Interrupts */ + uint32_t IC_CLR_RX_UNDER; /*!< (0x44) : Clear RX_UNDER Interrupt */ + uint32_t IC_CLR_RX_OVER; /*!< (0x48) : Clear RX_OVER Interrupt */ + uint32_t IC_CLR_TX_OVER; /*!< (0x4c) : Clear TX_OVER Interrupt */ + uint32_t IC_CLR_RD_REQ; /*!< (0x50) : Clear RQ_REQ Interrupt */ + uint32_t IC_CLR_TX_ABRT; /*!< (0x54) : Clear TX_ABRT Interrupt */ + uint32_t IC_CLR_RX_DONE; /*!< (0x58) : Clear RX_DONE Interrupt */ + uint32_t IC_CLR_ACTIVITY; /*!< (0x5c) : Clear ACTIVITY Interrupt */ + uint32_t IC_CLR_STOP_DET; /*!< (0x60) : Clear STOP_DET Interrupt */ + uint32_t IC_CLR_START_DET; /*!< (0x64) : Clear START_DET Interrupt */ + uint32_t IC_CLR_GEN_CALL; /*!< (0x68) : Clear GEN_CALL Interrupt */ + uint32_t IC_ENABLE; /*!< (0x6c) : IIC Enable */ + uint32_t IC_STATUS; /*!< (0x70) : IIC Status */ + uint32_t IC_TXFLR; /*!< (0x74) : Transmit FIFO Level Register */ + uint32_t IC_RXFLR; /*!< (0x78) : Receive FIFO Level Register */ + uint32_t IC_SDA_HOLD; /*!< (0x7c) : SDA Hold Time Length Reg */ + uint32_t IC_TX_ABRT_SOURCE; /*!< (0x80) : IIC Transmit Abort Status Reg */ + uint32_t IC_SLV_DATA_NACK_ONLY; /*!< (0x84) : Generate SLV_DATA_NACK Register */ + uint32_t IC_DMA_CR; /*!< (0x88) : DMA Control Register */ + uint32_t IC_DMA_TDLR; /*!< (0x8c) : DMA Transmit Data Level */ + uint32_t IC_DMA_RDLR; /*!< (0x90) : DMA Receive Data Level */ + uint32_t IC_SDA_SETUP; /*!< (0x94) : SDA Setup Register */ + uint32_t IC_ACK_GENERAL_CALL; /*!< (0x98) : ACK General Call Register */ + uint32_t IC_ENABLE_STATUS; /*!< (0x9c) : Enable Status Register */ + uint32_t IC_FS_SPKLEN; /*!< (0xa0) : ISS and FS spike suppression limit */ + uint32_t IC_HS_SPKLEN; /*!< (0xa4) : HS spike suppression limit */ + uint32_t RESERVED[19]; /*!< (0xa8) : Reserved */ + uint32_t IC_COMP_PARAM_1; /*!< (0xf4) : Component Parameter Register */ + uint32_t IC_COMP_VERSION; /*!< (0xf8) : Component Version ID Reg */ + uint32_t IC_COMP_TYPE; /*!< (0xfc) : Component Type Reg */ +} DW_IIC_REG, *DW_IIC_REG_PTR; +/** @} */ + +/** Spike Suppression Limit Configurations */ +typedef struct dw_iic_spklen { + uint32_t fs_spklen; /*!< value for IC_FS_SPKLEN, Tsp for fast mode is 50ns */ + uint32_t hs_spklen; /*!< value for IC_HS_SPKLEN, Tsp for high-speed mode is 10ns */ +} DW_IIC_SPKLEN, *DW_IIC_SPKLEN_PTR; + +/** IIC Clock SCL High and Low Count Configurations for Different Speed */ +typedef struct dw_iic_scl_cnt { + uint32_t ss_scl_hcnt; /*!< value for IC_SS_SCL_HCNT */ + uint32_t ss_scl_lcnt; /*!< value for IC_SS_SCL_LCNT */ + uint32_t fs_scl_hcnt; /*!< value for IC_FS_SCL_HCNT */ + uint32_t fs_scl_lcnt; /*!< value for IC_FS_SCL_LCNT */ + uint32_t hs_scl_hcnt; /*!< value for IC_HS_SCL_HCNT */ + uint32_t hs_scl_lcnt; /*!< value for IC_HS_SCL_LCNT */ +} DW_IIC_SCL_CNT, *DW_IIC_SCL_CNT_PTR; + +#define DW_IIC_GINT_DISABLED (0) /*!< designware interrupt disabled for control iic irq/fiq */ +#define DW_IIC_GINT_ENABLE (1<<0) /*!< designware interrupt enabled for control iic irq/fiq */ +#define DW_IIC_TXINT_ENABLE (1<<1) /*!< designware interrupt enabled for control transmit process */ +#define DW_IIC_RXINT_ENABLE (1<<2) /*!< designware interrupt enabled for control transmit process */ + +typedef struct dw_iic_buffer { + DEV_BUFFER *buf; + uint32_t ofs; + uint32_t len; +} DW_IIC_BUFFER, *DW_IIC_BUFFER_PTR; + +/** + * \brief DesignWare IIC control structure definition + * \details implement of dev_iic_info::iic_ctrl + */ +typedef struct dw_iic_ctrl { + DW_IIC_REG *dw_iic_regs; /*!< iic device registers */ + /* Variables which should be set during object implementation */ + uint32_t support_modes; /*!< supported iic modes */ + uint32_t tx_fifo_len; /*!< transmit fifo length */ + uint32_t rx_fifo_len; /*!< receive fifo length */ + uint32_t iic_master_code; /*!< value for IC_HS_MADDR */ + uint32_t retry_cnt; /*!< retry count for TX or RX */ + uint32_t intno; /*!< iic interrupt vector number */ + INT_HANDLER dw_iic_int_handler; /*!< iic interrupt handler */ + DW_IIC_SPKLEN iic_spklen; /*!< iic spike suppression length settings */ + DW_IIC_SCL_CNT iic_scl_cnt; /*!< iic scl count settings */ + /* Variables which always change during iic operation */ + uint32_t int_status; /*!< iic interrupt status */ + uint32_t iic_tx_over; /*!< iic tx overflow count */ + uint32_t iic_rx_over; /*!< iic rx overflow count */ + DW_IIC_BUFFER dw_iic_rxbuf; /*!< iic read buffer for receive data */ +} DW_IIC_CTRL, *DW_IIC_CTRL_PTR; + +/*!< One possible value for \ref dw_iic_ctrl::retry_cnt */ +#define DW_IIC_MAX_RETRY_COUNT (100000) + +#if DW_IIC_USE_IC_CLK_MHZ == 100 /*!< 100MHz */ +/*!< One possible value for \ref dw_iic_ctrl::iic_spklen */ +static const DW_IIC_SPKLEN dw_iic_spklen_const = {5, 1}; + +/*!< One possible value for \ref dw_iic_ctrl::iic_spklen */ +#if DW_IIC_USE_HS_BUS_LOADING_100PF +static const DW_IIC_SCL_CNT dw_iic_sclcnt_const = {0x0190, 0x01d6, 0x003c, 0x0082, 0x6, 0x10}; +#else +static const DW_IIC_SCL_CNT dw_iic_sclcnt_const = {0x0190, 0x01d6, 0x003c, 0x0082, 0xc, 0x20}; +#endif + +#elif DW_IIC_USE_IC_CLK_MHZ == 50 /* 50MHz */ +/*!< One possible value for \ref dw_iic_ctrl::iic_spklen */ +static const DW_IIC_SPKLEN dw_iic_spklen_const = {5, 1}; + +/*!< One possible value for \ref dw_iic_ctrl::iic_spklen */ +#if DW_IIC_USE_HS_BUS_LOADING_100PF +static const DW_IIC_SCL_CNT dw_iic_sclcnt_const = {0x00c8, 0x00eb, 0x001e, 0x0041, 0x6, 0x8}; +#else +static const DW_IIC_SCL_CNT dw_iic_sclcnt_const = {0x00c8, 0x00eb, 0x001e, 0x0041, 0x6, 0x10}; +#endif + +#else /* Default 100MHz */ +/*!< One possible value for \ref dw_iic_ctrl::iic_spklen */ +static const DW_IIC_SPKLEN dw_iic_spklen_const = {5, 1}; + +/*!< One possible value for \ref dw_iic_ctrl::iic_spklen */ +#if DW_IIC_USE_HS_BUS_LOADING_100PF +static const DW_IIC_SCL_CNT dw_iic_sclcnt_const = {0x0190, 0x01d6, 0x003c, 0x0082, 0x6, 0x10}; +#else +static const DW_IIC_SCL_CNT dw_iic_sclcnt_const = {0x0190, 0x01d6, 0x003c, 0x0082, 0xc, 0x20}; +#endif + +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \defgroup DEVICE_DW_IIC_FUNCDLR DesignWare IIC Function Declaration + * \ingroup DEVICE_DW_IIC + * \brief Contains declarations of designware iic functions. + * \details This are only used in iic object implementation source file + * @{ + */ +extern int32_t dw_iic_open (DEV_IIC *iic_obj, uint32_t mode, uint32_t param); +extern int32_t dw_iic_close (DEV_IIC *iic_obj); +extern int32_t dw_iic_control (DEV_IIC *iic_obj, uint32_t ctrl_cmd, void *param); +extern int32_t dw_iic_write (DEV_IIC *iic_obj, const void *data, uint32_t len); +extern int32_t dw_iic_read (DEV_IIC *iic_obj, void *data, uint32_t len); +extern void dw_iic_isr(DEV_IIC *iic_obj, void *ptr); + +#ifdef __cplusplus +} +#endif + +/** @} */ + +#endif /* _DW_IIC_H_ */ diff --git a/hw/mcu/arc/src/ext/sdk/device/designware/iic/dw_iic_hal.h b/hw/mcu/arc/src/ext/sdk/device/designware/iic/dw_iic_hal.h new file mode 100644 index 000000000..f7ec0d27a --- /dev/null +++ b/hw/mcu/arc/src/ext/sdk/device/designware/iic/dw_iic_hal.h @@ -0,0 +1,186 @@ +/* ------------------------------------------ + * Copyright (c) 2017, Synopsys, Inc. All rights reserved. + + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + + * 1) Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + + * 2) 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. + + * 3) Neither the name of the Synopsys, Inc., nor the names of its contributors may + * be used to endorse or promote products derived from this software without + * specific prior written permission. + + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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. + * + * \version 2017.03 + * \date 2014-06-30 + * \author Huaqi Fang(Huaqi.Fang@synopsys.com) +--------------------------------------------- */ + +/** + * \file + * \ingroup DEVICE_DW_IIC + * \brief DesignWare IIC driver hardware description related header file + * \details detailed hardware related definitions of DesignWare IIC driver + */ + +#ifndef _DEVICE_DW_IIC_HAL_H_ +#define _DEVICE_DW_IIC_HAL_H_ + +#include "device/designware/iic/dw_iic_hal_cfg.h" + +/** Enable Designware IIC */ +#define DW_IIC_ENABLE (1) +/** Disable Designware IIC */ +#define DW_IIC_DISABLE (0) + +/** Stop Condition issue after this byte */ +#define IC_DATA_CMD_STOP (1 << 9) +/** Restart Condition issue after this byte */ +#define IC_DATA_CMD_RESTART (1 << 10) +/** No Restart or stop condition after this byte */ +#define IC_DATA_CMD_NONE (0) + +/** Perform a write request */ +#define IC_DATA_CMD_WRITE_REQ (0) +/** Perform a read request */ +#define IC_DATA_CMD_READ_REQ (1 << 8) + +/** Fields of IC_CON register */ +/* DW_APB I2C IP Config Dependencies. */ +#if DW_IIC_ALLOW_RESTART +#define IC_CON_RESTART_EN (1 << 5) +#else +#define IC_CON_RESTART_EN (0x00) +#endif + +/* Master Addressing Mode Config */ +#if DW_IIC_MST_10_BIT_ADDR_SUPPORT +#define MST_10_BIT_ADDR_MODE (1 << 4) +#define IC_10BITADDR_MASTER (1 << 12) +#else +#define MST_10_BIT_ADDR_MODE (0x00) +#define IC_10BITADDR_MASTER (0x00) +#endif + +/* Slave Addressing Mode Config */ +#if DW_IIC_SLV_10_BIT_ADDR_SUPPORT +#define SLV_10_BIT_ADDR_MODE (1 << 3) +#else +#define SLV_10_BIT_ADDR_MODE (0x00) +#endif + +#if DW_IIC_SPECIAL_START_BYTE +#define IC_TAR_SPECIAL (1 << 11) +#define IC_TAR_GC_OR_START (1 << 10) +#else +#define IC_TAR_SPECIAL (0x00) +#define IC_TAR_GC_OR_START (0x00) +#endif + +/** 7bit IIC address mask for target address register */ +#define IC_TAR_7BIT_ADDR_MASK (0x7F) +/** 7bit IIC address mask for slave address register */ +#define IC_SAR_7BIT_ADDR_MASK (0x7F) +/** 10bit IIC address mask for target address register */ +#define IC_TAR_10BIT_ADDR_MASK (0x3FF) +/** 10bit IIC address mask for slave address register */ +#define IC_SAR_10BIT_ADDR_MASK (0x3FF) + +/** Speed modes of IC_CON */ +#define IC_CON_SPEED_MASK (0x6) +#define IC_CON_SPEED_STANDARD (0x2) +#define IC_CON_SPEED_FAST (0x4) +#define IC_CON_SPEED_HIGH (0x6) +/** Working mode of IC_CON */ +#define IC_CON_MST_SLV_MODE_MASK (0x41) +#define IC_CON_ENA_MASTER_MODE (0x41) +#define IC_CON_ENA_SLAVE_MODE (0) + +/* IIC interrupt control */ +#define IC_INT_DISABLE_ALL (0x0) +#define IC_INT_ENABLE_ALL (0x7FF) +/* Interrupt Register Fields */ +#define IC_INTR_STAT_GEN_CALL (1 << 11) +#define IC_INTR_STAT_START_DET (1 << 10) +#define IC_INTR_STAT_STOP_DET (1 << 9) +#define IC_INTR_STAT_ACTIVITY (1 << 8) +#define IC_INTR_STAT_RX_DONE (1 << 7) +#define IC_INTR_STAT_TX_ABRT (1 << 6) +#define IC_INTR_STAT_RD_REQ (1 << 5) +#define IC_INTR_STAT_TX_EMPTY (1 << 4) +#define IC_INTR_STAT_TX_OVER (1 << 3) +#define IC_INTR_STAT_RX_FULL (1 << 2) +#define IC_INTR_STAT_RX_OVER (1 << 1) +#define IC_INTR_STAT_RX_UNDER (1 << 0) + +/* Interrupt enable mask as master */ +#define IC_INT_MST_TX_ENABLE (IC_INTR_STAT_TX_EMPTY|IC_INTR_STAT_TX_OVER|IC_INTR_STAT_TX_ABRT) +#define IC_INT_MST_RX_ENABLE (IC_INTR_STAT_TX_EMPTY|IC_INTR_STAT_RX_FULL|IC_INTR_STAT_RX_OVER|IC_INTR_STAT_RX_UNDER|IC_INTR_STAT_TX_ABRT) + +/* Interrupt enable mask as master */ +#define IC_INT_SLV_COMMON_ENABLE (IC_INTR_STAT_START_DET|IC_INTR_STAT_STOP_DET) +#define IC_INT_SLV_TX_ENABLE (IC_INTR_STAT_RD_REQ|IC_INTR_STAT_TX_ABRT) +#define IC_INT_SLV_RX_ENABLE (IC_INTR_STAT_RX_FULL|IC_INTR_STAT_RX_OVER|IC_INTR_STAT_RX_UNDER) + +/* IC_ENABLE_STATUS Bits */ +#define IC_ENABLE_STATUS_IC_EN (1 << 0) +#define IC_ENABLE_STATUS_SLV_DIS (1 << 1) +#define IC_ENABLE_STATUS_SLV_RX_LOST (1 << 2) + +/* IIC TX & RX threshold settings */ +#define IIC_TX_THRESHOLD (0) +#define IIC_RX_THRESHOLD (0) + +/* DW_APB IIC (DW_IC_STATUS) Status Register Fields. */ +#define IC_STATUS_ACTIVITY (0x01) +#define IC_STATUS_TFNF (0x02) /* (1 << 1) */ +#define IC_STATUS_TFE (0x04) /* (1 << 2) */ +#define IC_STATUS_RFNE (0x08) /* (1 << 3) */ +#define IC_STATUS_RFF (0x10) /* (1 << 4) */ +#define IC_STATUS_MASTER_ACT (0x20) /* (1 << 5) */ +#define IC_STATUS_SLAVE_ACT (0x40) /* (1 << 6) */ + +/* IC_TX_ABRT_SOURCE Register Bit Fields */ +#define IC_TX_ABRT_7B_ADDR_NOACK (1 << 0) +#define IC_TX_ABRT_10ADDR1_NOACK (1 << 1) +#define IC_TX_ABRT_10ADDR2_NOACK (1 << 2) +#define IC_TX_ABRT_TXDATA_NOACK (1 << 3) +#define IC_TX_ABRT_GCALL_NOACK (1 << 4) +#define IC_TX_ABRT_GCALL_READ (1 << 5) +#define IC_TX_ABRT_HS_ACKDET (1 << 6) +#define IC_TX_ABRT_SBYTE_ACKDET (1 << 7) +#define IC_TX_ABRT_HS_NORSTRT (1 << 8) +#define IC_TX_ABRT_SBYTE_NORSTRT (1 << 9) +#define IC_TX_ABRT_10B_RD_NORSTRT (1 << 10) +#define IC_TX_ABRT_MASTER_DIS (1 << 11) +#define IC_TX_ABRT_ARB_LOST (1 << 12) +#define IC_TX_ABRT_SLVFLUSH_TXFIFO (1 << 13) +#define IC_TX_ABRT_SLV_ARBLOST (1 << 14) +#define IC_TX_ABRT_SLVRD_INTX (1 << 15) + +/* Combined bits for iic abort source as master */ +#define IIC_MST_ABRT_ADDR_NOACK (IC_TX_ABRT_7B_ADDR_NOACK|IC_TX_ABRT_10ADDR1_NOACK|IC_TX_ABRT_10ADDR1_NOACK) +#define IIC_MST_ABRT_LOST_BUS (IC_TX_ABRT_ARB_LOST) +#define IIC_MST_ABRT_DATA_NOACK (IC_TX_ABRT_TXDATA_NOACK) + +/* Combined bits for iic abort source as slave */ +#define IIC_SLV_ABRT_LOST_BUS (IC_TX_ABRT_ARB_LOST|IC_TX_ABRT_SLV_ARBLOST) + +/** @} */ + +#endif /* _DEVICE_DW_IIC_HAL_H_ */ diff --git a/hw/mcu/arc/src/ext/sdk/device/designware/iic/dw_iic_hal_cfg.h b/hw/mcu/arc/src/ext/sdk/device/designware/iic/dw_iic_hal_cfg.h new file mode 100644 index 000000000..107316217 --- /dev/null +++ b/hw/mcu/arc/src/ext/sdk/device/designware/iic/dw_iic_hal_cfg.h @@ -0,0 +1,82 @@ +/* ------------------------------------------ + * Copyright (c) 2017, Synopsys, Inc. All rights reserved. + + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + + * 1) Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + + * 2) 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. + + * 3) Neither the name of the Synopsys, Inc., nor the names of its contributors may + * be used to endorse or promote products derived from this software without + * specific prior written permission. + + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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. + * + * \version 2017.03 + * \date 2014-07-01 + * \author Huaqi Fang(Huaqi.Fang@synopsys.com) +--------------------------------------------- */ + +/** + * \file + * \ingroup DEVICE_DW_IIC + * \brief DesignWare IIC driver hardware description + * related header file configuration file + * \details configuration file to enable or disable some function of iic + */ + +#ifndef _DEVICE_DW_IIC_HAL_CFG_H_ +#define _DEVICE_DW_IIC_HAL_CFG_H_ + +#ifndef DW_IIC_ALLOW_RESTART +#define DW_IIC_ALLOW_RESTART (1) /*!< allow restart configuration */ +#endif + +#ifdef DW_IIC_SPECIAL_START_BYTE +#define DW_IIC_SPECIAL_START_BYTE (0) /*!< SPECIAL bit enable in IC_TAR */ +#endif + +#ifndef DW_IIC_MST_10_BIT_ADDR_SUPPORT +#define DW_IIC_MST_10_BIT_ADDR_SUPPORT (1) /*!< enable 10-bit address mode */ +#endif + +#ifdef DW_IIC_SLV_10_BIT_ADDR_SUPPORT +#define DW_IIC_SLV_10_BIT_ADDR_SUPPORT (1) /*!< slave 10-bit addressing mode */ +#endif + +#ifndef DW_IIC_DYNAMIC_TAR_UPDATE_SUPPORT +#define DW_IIC_DYNAMIC_TAR_UPDATE_SUPPORT (0) /*!< Dynamic target address update support */ +#endif + +#ifndef DW_IIC_DISABLE_MAX_T_POLL_CNT +#define DW_IIC_DISABLE_MAX_T_POLL_CNT (1250) /*!< Timeout count, approximate to be 25us in 50MHz CPU @ Standard mode */ +#endif + +#ifndef DW_IIC_CALC_FIFO_LEN_ENABLE +#define DW_IIC_CALC_FIFO_LEN_ENABLE (1) /*!< Default enable calculate fifo length */ +#endif + +#ifndef DW_IIC_USE_IC_CLK_MHZ +#define DW_IIC_USE_IC_CLK_MHZ (50) /*!< Default use 50MHz IC_CLK */ +#endif + +#ifndef DW_IIC_USE_HS_BUS_LOADING_100PF +#define DW_IIC_USE_HS_BUS_LOADING_100PF (1) /*!< Use bus loading 100pf */ +#endif + +#endif /* _DEVICE_DW_IIC_HAL_CFG_H_ */ + diff --git a/hw/mcu/arc/src/ext/sdk/device/designware/spi/dw_spi.c b/hw/mcu/arc/src/ext/sdk/device/designware/spi/dw_spi.c new file mode 100644 index 000000000..bea413b41 --- /dev/null +++ b/hw/mcu/arc/src/ext/sdk/device/designware/spi/dw_spi.c @@ -0,0 +1,1337 @@ +/* ------------------------------------------ + * Copyright (c) 2017, Synopsys, Inc. All rights reserved. + + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + + * 1) Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + + * 2) 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. + + * 3) Neither the name of the Synopsys, Inc., nor the names of its contributors may + * be used to endorse or promote products derived from this software without + * specific prior written permission. + + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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. + * + * \version 2017.03 + * \date 2014-06-25 + * \author Huaqi Fang(Huaqi.Fang@synopsys.com) +--------------------------------------------- */ + +/** + * \defgroup DEVICE_DW_SPI Designware SPI Driver + * \ingroup DEVICE_DW + * \brief Designware SPI Driver Implementation + */ + +/** + * \file + * \brief DesignWare SPI driver implementation based on device hal layer definition (\ref dev_spi.h) + * \ingroup DEVICE_DW_SPI + */ +#include + +#include "inc/embARC_toolchain.h" +#include "inc/embARC_error.h" + +#include "inc/arc/arc_exception.h" + +#include "device/designware/spi/dw_spi_hal.h" +#include "device/designware/spi/dw_spi.h" + +/** + * \defgroup DEVICE_DW_SPI_DEFINES DesignWare SPI Driver Macros + * \ingroup DEVICE_DW_SPI + * \brief DesignWare SPI driver macros used in spi driver + * @{ + */ +/** check expressions used in DesignWare SPI driver implementation */ +#define DW_SPI_CHECK_EXP(EXPR, ERROR_CODE) CHECK_EXP(EXPR, ercd, ERROR_CODE, error_exit) + +/** convert DesignWare frequence to divisor */ +#define DW_SPI_FREQ2DV(perifreq, spifreq) ((perifreq) / (spifreq)) + +#ifndef DISABLE_DEVICE_OBJECT_VALID_CHECK +/** valid check of spi info object */ +#define VALID_CHK_SPI_INFO_OBJECT(spiinfo_obj_ptr) { \ + DW_SPI_CHECK_EXP((spiinfo_obj_ptr)!=NULL, E_OBJ); \ + DW_SPI_CHECK_EXP(((spiinfo_obj_ptr)->spi_ctrl)!=NULL, E_OBJ); \ + } +#endif + +/** + * \defgroup DEVICE_DW_SPI_DEF_CBR DesignWare SPI Interrupt Callback Routine Select Marcos + * \ingroup DEVICE_DW_SPI_DEFINES + * \brief DesignWare SPI interrupt callback routines select macros definitions + * @{ + */ +#define DW_SPI_RDY_SND (1U) /*!< ready to send callback */ +#define DW_SPI_RDY_RCV (2U) /*!< ready to receive callback */ +#define DW_SPI_RDY_XFER (3U) /*!< ready to transfer callback */ +/** @} */ + +/** @} */ + +/** + * \defgroup DEVICE_DW_SPI_STATIC DesignWare SPI Driver Static Functions + * \ingroup DEVICE_DW_SPI + * \brief Static or inline functions, variables for DesignWare SPI handle spi operations, + * only used in this file. + * @{ + */ + +/** Disable designware spi device */ +Inline void dw_spi_disable(DW_SPI_REG *spi_reg_ptr) +{ +/** disable spi operations, then program spi control regs is possible */ + spi_reg_ptr->SSIENR = DW_SPI_SSI_DISABLE; +} +/** Enable designware spi device */ +Inline void dw_spi_enable(DW_SPI_REG *spi_reg_ptr) +{ + spi_reg_ptr->SSIENR = DW_SPI_SSI_ENABLE; +} + +/** Clear all designware spi interrupt */ +Inline void dw_spi_clear_interrupt_all(DW_SPI_REG *spi_reg_ptr) +{ + (void)spi_reg_ptr->ICR; +} + +/** test whether spi is busy, busy return 1, else 0 */ +Inline int32_t dw_spi_busy(DW_SPI_REG *spi_reg_ptr) +{ + return ((spi_reg_ptr->SR & DW_SPI_SR_BUSY) != 0); +} +/** test whether spi is ready to send, 1 ready, 0 not ready */ +Inline int32_t dw_spi_putready(DW_SPI_REG *spi_reg_ptr) +{ + return ((spi_reg_ptr->SR & DW_SPI_SR_TFNF) != 0); +} +/** test whether spi is read to receive, 1 ready, 0 not ready */ +Inline int32_t dw_spi_getready(DW_SPI_REG *spi_reg_ptr) +{ + return ((spi_reg_ptr->SR & DW_SPI_SR_RFNE) != 0); +} +/** write data to spi send fifo */ +Inline void dw_spi_putdata(DW_SPI_REG *spi_reg_ptr, int32_t data) +{ + spi_reg_ptr->DATAREG = (uint32_t)data; +} +/** read data from spi receive fifo, return data received */ +Inline int32_t dw_spi_getdata(DW_SPI_REG *spi_reg_ptr) +{ + return (int32_t)spi_reg_ptr->DATAREG; +} +/** + * \brief send data by spi when available, + * mostly used in interrupt method, non-blocked function + * \param[in] spi_reg_ptr spi register structure pointer + * \param[in] data data to be sent + * \retval E_OK send successfully + * \retval E_OBJ not ready to send data + */ +Inline int32_t dw_spi_snd_dat(DW_SPI_REG *spi_reg_ptr, int32_t data) +{ + if (dw_spi_putready(spi_reg_ptr)) { + dw_spi_putdata(spi_reg_ptr, data); + return E_OK; + } + return E_OBJ; +} +/** + * \brief receive one char from spi, + * mostly used in interrupt routine, non-blocked function + * \param[in] spi_reg_ptr spi register structure pointer + * \return data received by the spi + */ +Inline int32_t dw_spi_rcv_dat(DW_SPI_REG *spi_reg_ptr) +{ + return dw_spi_getdata(spi_reg_ptr); +} +/** + * \brief send char by spi in poll method, blocked function + * \param[in] spi_reg_ptr spi register structure pointer + * \param[in] data data to be sent + */ +Inline void dw_spi_psnd_dat(DW_SPI_REG *spi_reg_ptr, int32_t data) +{ + /** wait until spi is ready to send */ + while (!dw_spi_putready(spi_reg_ptr)); /* blocked */ + /** send char */ + dw_spi_putdata(spi_reg_ptr, data); +} +/** + * \brief receive one char from spi in poll method, blocked function + * \param[in] spi_reg_ptr spi register structure pointer + * \return data received by the spi + */ +Inline int32_t dw_spi_prcv_dat(DW_SPI_REG *spi_reg_ptr) +{ + /** wait until spi is ready to receive */ + while (!dw_spi_getready(spi_reg_ptr)); /* blocked */ + /** receive data */ + return dw_spi_getdata(spi_reg_ptr); +} + +/** Reset designware FIFO by disable spi device, then enable device */ +Inline void dw_spi_reset_fifo(DW_SPI_REG *spi_reg_ptr) +{ + dw_spi_disable(spi_reg_ptr); + dw_spi_enable(spi_reg_ptr); +} + +/** Enable designware spi bit interrupt with mask */ +Inline void dw_spi_unmask_interrupt(DW_SPI_REG *spi_reg_ptr, uint32_t mask) +{ + spi_reg_ptr->IMR |= mask; +} + +/** Disable designware spi bit interrupt with mask */ +Inline void dw_spi_mask_interrupt(DW_SPI_REG *spi_reg_ptr, uint32_t mask) +{ + spi_reg_ptr->IMR &= ~mask; +} + +/** Set designware spi device frequency */ +Inline void dw_spi_set_freq(DW_SPI_CTRL *spi_ctrl_ptr, uint32_t freq) +{ + uint32_t sck_divisor; + DW_SPI_REG *spi_reg_ptr = spi_ctrl_ptr->dw_spi_regs; + + dw_spi_disable(spi_reg_ptr); + + sck_divisor = DW_SPI_FREQ2DV(spi_ctrl_ptr->dw_apb_bus_freq, freq); + spi_reg_ptr->BAUDR = sck_divisor; + dw_spi_enable(spi_reg_ptr); +} + +/** Set designware spi device data frame size */ +static int32_t dw_spi_set_dfs(DW_SPI_REG *spi_reg_ptr, uint32_t dfs) +{ + uint32_t ctrl0_reg; + if ((dfs <= 3) || (dfs > 16)) return -1; + + dw_spi_disable(spi_reg_ptr); + ctrl0_reg = spi_reg_ptr->CTRLR0; + ctrl0_reg &= ~(DW_SPI_CTRLR0_DFS_MASK); + spi_reg_ptr->CTRLR0 = ctrl0_reg | (dfs-1); + dw_spi_enable(spi_reg_ptr); + + return 0; +} + +/** Choose proper designware spi clock mode setting value */ +Inline uint32_t dw_spi_select_clockmode(uint32_t clk_mode) +{ + return (clk_mode << DW_SPI_CTRLR0_SC_OFS); +} + +/** Set designware spi clock mode */ +Inline int32_t dw_spi_set_clockmode(DW_SPI_REG *spi_reg_ptr, uint32_t clk_mode) +{ + if (clk_mode > SPI_CPOL_1_CPHA_1) { + return -1; + } + dw_spi_disable(spi_reg_ptr); + spi_reg_ptr->CTRLR0 &= ~(DW_SPI_CTRLR0_SC_MASK); + spi_reg_ptr->CTRLR0 |= dw_spi_select_clockmode(clk_mode); + dw_spi_enable(spi_reg_ptr); + return 0; +} + +/** Select a spi slave with slv_line */ +Inline int32_t dw_spi_select_slave(DW_SPI_REG *spi_reg_ptr, uint32_t slv_line) +{ + /* check if spi busy */ + if (dw_spi_busy(spi_reg_ptr)) return -1; + + spi_reg_ptr->SER = 1<SER = 0; + return 0; +} + +Inline void dw_spi_flush_tx(DW_SPI_REG *spi_reg_ptr) +{ + dw_spi_reset_fifo(spi_reg_ptr); +} + +Inline void dw_spi_flush_rx(DW_SPI_REG *spi_reg_ptr) +{ + dw_spi_reset_fifo(spi_reg_ptr); +} + +/** Get TX FIFO Length. + * calculate spi fifo length using fifo threshold method + * If you attempt to set bits [7:0] of this register to + * a value greater than or equal to the depth of the FIFO, + * this field is not written and retains its current value. + */ +static uint32_t dw_spi_get_txfifo_len(DW_SPI_REG *spi_reg_ptr) +{ + uint32_t fifo_thr_lev_tmp, left, right, i; + + fifo_thr_lev_tmp = spi_reg_ptr->TXFTLR; + + if (fifo_thr_lev_tmp != 0) { + left = fifo_thr_lev_tmp; + } else { + left = DW_SPI_MIN_FIFO_LENGTH; + } + right = DW_SPI_MAX_FIFO_LENGTH + 1; + + for (i = left; i <= right; i++) { + spi_reg_ptr->TXFTLR = i; + if (spi_reg_ptr->TXFTLR != i) { + break; + } + } + spi_reg_ptr->TXFTLR = fifo_thr_lev_tmp; /* restore old fifo threshold */ + + return (i); +} + +/** Get RX FIFO Length */ +static uint32_t dw_spi_get_rxfifo_len(DW_SPI_REG *spi_reg_ptr) +{ + uint32_t fifo_thr_lev_tmp, left, right, i; + + fifo_thr_lev_tmp = spi_reg_ptr->RXFTLR; + + if (fifo_thr_lev_tmp != 0) { + left = fifo_thr_lev_tmp; + } else { + left = DW_SPI_MIN_FIFO_LENGTH; + } + right = DW_SPI_MAX_FIFO_LENGTH + 1; + + for (i = left; i <= right; i++) { + spi_reg_ptr->RXFTLR = i; + if (spi_reg_ptr->RXFTLR != i) { + break; + } + } + spi_reg_ptr->RXFTLR = fifo_thr_lev_tmp; /* restore old fifo threshold */ + + return (i); +} + +/** Init Designware SPI Hardware */ +static void dw_spi_hw_init(DW_SPI_CTRL *spi_ctrl_ptr, uint32_t clk_mode, uint32_t dfs) +{ + uint32_t ctrl0_reg = 0; + DW_SPI_REG *spi_reg_ptr = spi_ctrl_ptr->dw_spi_regs; + + dw_spi_disable(spi_reg_ptr); + + /* Clear interrupts */ + ctrl0_reg = spi_reg_ptr->ICR; + /* Mask all interrupts */ + spi_reg_ptr->IMR = 0; + + ctrl0_reg = DW_SPI_CTRLR0_FRF_MOTOROLA | DW_SPI_TMOD_TRANSMIT_RECEIVE \ + | dw_spi_select_clockmode(clk_mode) | (dfs - 1) | DW_SPI_CTRLR0_SLV_OE_ENABLE; + spi_reg_ptr->CTRLR0 = ctrl0_reg; + spi_reg_ptr->CTRLR1 = 0; + + /* deselect slaves */ + spi_reg_ptr->SER = 0; + + /* Set threshold values for both tx and rx */ + spi_reg_ptr->TXFTLR = 0; + spi_reg_ptr->RXFTLR = 0; + + dw_spi_enable(spi_reg_ptr); +} + +/** enable designware spi */ +static void dw_spi_enable_device(DEV_SPI_INFO *spi_info_ptr) +{ + DW_SPI_CTRL *spi_ctrl_ptr = (DW_SPI_CTRL *)(spi_info_ptr->spi_ctrl); + DW_SPI_REG *spi_reg_ptr = (DW_SPI_REG *)(spi_ctrl_ptr->dw_spi_regs); + + if ((spi_info_ptr->status & DEV_ENABLED) == 0) { + dw_spi_enable(spi_reg_ptr); + spi_info_ptr->status |= DEV_ENABLED; + } +} + +/** disable designware spi */ +static void dw_spi_disable_device(DEV_SPI_INFO *spi_info_ptr) +{ + DW_SPI_CTRL *spi_ctrl_ptr = (DW_SPI_CTRL *)(spi_info_ptr->spi_ctrl); + DW_SPI_REG *spi_reg_ptr = (DW_SPI_REG *)(spi_ctrl_ptr->dw_spi_regs); + + dw_spi_disable(spi_reg_ptr); + spi_info_ptr->status &= ~DEV_ENABLED; +} + + +/** + * \brief disable designware spi send or receive interrupt + * \param[in] DEV_SPI_INFO *spi_info_ptr + * \param[in] cbrtn control code of callback routine of send or receive + */ +static int32_t dw_spi_dis_cbr(DEV_SPI_INFO *spi_info_ptr, uint32_t cbrtn) +{ + DW_SPI_CTRL *spi_ctrl_ptr = (DW_SPI_CTRL *)(spi_info_ptr->spi_ctrl); + int32_t ercd = E_OK; + + if ((spi_info_ptr->status & DW_SPI_IN_XFER) != 0) { /* only in transfer need do check */ + switch (cbrtn) { + case DW_SPI_RDY_SND: + DW_SPI_CHECK_EXP((spi_info_ptr->status & DW_SPI_IN_XFER) == DW_SPI_IN_TX, E_CTX); + spi_info_ptr->status &= ~(DW_SPI_IN_TX); + break; + case DW_SPI_RDY_RCV: + DW_SPI_CHECK_EXP((spi_info_ptr->status & DW_SPI_IN_XFER) == DW_SPI_IN_RX, E_CTX); + spi_info_ptr->status &= ~(DW_SPI_IN_RX); + break; + case DW_SPI_RDY_XFER: + DW_SPI_CHECK_EXP((spi_info_ptr->status & DW_SPI_IN_XFER) == DW_SPI_IN_XFER, E_CTX); + spi_info_ptr->status &= ~(DW_SPI_IN_XFER); + break; + default: + break; + } + } + + dw_spi_mask_interrupt(spi_ctrl_ptr->dw_spi_regs, DW_SPI_IMR_XFER); + + if (spi_ctrl_ptr->int_status & DW_SPI_GINT_ENABLE) { + int_disable(spi_ctrl_ptr->intno); + spi_ctrl_ptr->int_status &= ~DW_SPI_GINT_ENABLE; + } + +error_exit: + return ercd; +} + +/** + * \brief enable DesignWare SPI send or receive interrupt + * \param[in] DEV_SPI_INFO *spi_info_ptr + * \param[in] cbrtn control code of callback routine of send or receive + */ +static int32_t dw_spi_ena_cbr(DEV_SPI_INFO *spi_info_ptr, uint32_t cbrtn) +{ + DW_SPI_CTRL *spi_ctrl_ptr = (DW_SPI_CTRL *)(spi_info_ptr->spi_ctrl); + int32_t ercd = E_OK; + + DW_SPI_CHECK_EXP((spi_info_ptr->status & DW_SPI_IN_XFER) == 0, E_CTX); + switch (cbrtn) { + case DW_SPI_RDY_SND: + spi_info_ptr->status |= DW_SPI_IN_TX; + break; + case DW_SPI_RDY_RCV: + spi_info_ptr->status |= DW_SPI_IN_RX; + break; + case DW_SPI_RDY_XFER: + spi_info_ptr->status |= DW_SPI_IN_XFER; + break; + default: + break; + } + dw_spi_unmask_interrupt(spi_ctrl_ptr->dw_spi_regs, DW_SPI_IMR_XFER); + + if ((spi_ctrl_ptr->int_status & DW_SPI_GINT_ENABLE) == 0) { + spi_ctrl_ptr->int_status |= DW_SPI_GINT_ENABLE; + int_enable(spi_ctrl_ptr->intno); + } + +error_exit: + return ercd; +} + +/** + * \brief enable designware spi interrupt + * \param spi_info_ptr spi information structure pointer + */ +static void dw_spi_enable_interrupt(DEV_SPI_INFO *spi_info_ptr) +{ + DW_SPI_CTRL *spi_ctrl_ptr = (DW_SPI_CTRL *)(spi_info_ptr->spi_ctrl); + + int_handler_install(spi_ctrl_ptr->intno, spi_ctrl_ptr->dw_spi_int_handler); + spi_ctrl_ptr->int_status |= DW_SPI_GINT_ENABLE; + int_enable(spi_ctrl_ptr->intno); /** enable spi interrupt */ +} +/** + * \brief disable designware spi interrupt + * \param spi_info_ptr spi information structure pointer + */ +static void dw_spi_disable_interrupt(DEV_SPI_INFO *spi_info_ptr) +{ + DW_SPI_CTRL *spi_ctrl_ptr = (DW_SPI_CTRL *)(spi_info_ptr->spi_ctrl); + + /** disable spi send&receive interrupt after disable spi interrupt */ + dw_spi_dis_cbr(spi_info_ptr, DW_SPI_RDY_SND); + dw_spi_dis_cbr(spi_info_ptr, DW_SPI_RDY_RCV); + dw_spi_dis_cbr(spi_info_ptr, DW_SPI_RDY_XFER); + /* disable spi interrupt */ + dw_spi_mask_interrupt(spi_ctrl_ptr->dw_spi_regs, DW_SPI_IMR_XFER); + spi_info_ptr->status &= ~DW_SPI_IN_XFER; + int_disable(spi_ctrl_ptr->intno); + spi_ctrl_ptr->int_status &= ~(DW_SPI_GINT_ENABLE); +} + +static void dw_spi_reset_device(DEV_SPI_INFO *spi_info_ptr) +{ + DW_SPI_CTRL *spi_ctrl_ptr = (DW_SPI_CTRL *)(spi_info_ptr->spi_ctrl); + DW_SPI_REG *spi_reg_ptr = (DW_SPI_REG *)(spi_ctrl_ptr->dw_spi_regs); + + dw_spi_disable_device(spi_info_ptr); + dw_spi_disable_interrupt(spi_info_ptr); + dw_spi_clear_interrupt_all(spi_reg_ptr); + dw_spi_enable_device(spi_info_ptr); +} + +/** abort current interrupt transmit transfer */ +static int32_t dw_spi_abort_tx(DEV_SPI *spi_obj) +{ + DEV_SPI_INFO *spi_info_ptr = &(spi_obj->spi_info); + int32_t ercd = E_OK; + + DW_SPI_CHECK_EXP((spi_info_ptr->status & DW_SPI_IN_XFER) != 0, E_OK); + DW_SPI_CHECK_EXP((spi_info_ptr->status & DW_SPI_IN_XFER) == DW_SPI_IN_TX, E_CTX); + + dw_spi_dis_cbr(spi_info_ptr, DW_SPI_RDY_SND); + spi_info_ptr->status |= DEV_IN_TX_ABRT; + if (spi_info_ptr->spi_cbs.tx_cb != NULL) { + spi_info_ptr->spi_cbs.tx_cb(spi_obj); + } + spi_info_ptr->status &= ~(DEV_IN_TX_ABRT); + +error_exit: + return ercd; +} + +/** abort current interrupt receive transfer */ +static int32_t dw_spi_abort_rx(DEV_SPI *spi_obj) +{ + DEV_SPI_INFO *spi_info_ptr = &(spi_obj->spi_info); + int32_t ercd = E_OK; + + DW_SPI_CHECK_EXP((spi_info_ptr->status & DW_SPI_IN_XFER) != 0, E_OK); + DW_SPI_CHECK_EXP((spi_info_ptr->status & DW_SPI_IN_XFER) == DW_SPI_IN_RX, E_CTX); + + dw_spi_dis_cbr(spi_info_ptr, DW_SPI_RDY_RCV); + spi_info_ptr->status |= DEV_IN_RX_ABRT; + if (spi_info_ptr->spi_cbs.rx_cb != NULL) { + spi_info_ptr->spi_cbs.rx_cb(spi_obj); + } + spi_info_ptr->status &= ~(DEV_IN_RX_ABRT); + +error_exit: + return ercd; +} + +/** abort current interrupt transfer */ +static int32_t dw_spi_abort_xfer(DEV_SPI *spi_obj) +{ + DEV_SPI_INFO *spi_info_ptr = &(spi_obj->spi_info); + int32_t ercd = E_OK; + + DW_SPI_CHECK_EXP((spi_info_ptr->status & DW_SPI_IN_XFER) != 0, E_OK); + DW_SPI_CHECK_EXP((spi_info_ptr->status & DW_SPI_IN_XFER) == DW_SPI_IN_XFER, E_CTX); + + dw_spi_dis_cbr(spi_info_ptr, DW_SPI_RDY_XFER); + spi_info_ptr->status |= DEV_IN_XFER_ABRT; + if (spi_info_ptr->spi_cbs.xfer_cb != NULL) { + spi_info_ptr->spi_cbs.xfer_cb(spi_obj); + } + spi_info_ptr->status &= ~(DEV_IN_XFER_ABRT); + +error_exit: + return ercd; +} + +/** Get available transmit fifo count */ +static int32_t dw_spi_get_txavail(DW_SPI_CTRL *spi_ctrl_ptr) +{ + int32_t tx_avail = 0; + DW_SPI_REG *spi_reg_ptr = (DW_SPI_REG *)(spi_ctrl_ptr->dw_spi_regs); + +#if DW_SPI_CALC_FIFO_LEN_ENABLE + if (spi_ctrl_ptr->tx_fifo_len <= 1) { + if (dw_spi_putready(spi_reg_ptr) == 1) { + tx_avail = 1; + } else { + tx_avail = 0; + } + } else +#endif + { + tx_avail = spi_ctrl_ptr->tx_fifo_len - spi_reg_ptr->TXFLR; + } + return tx_avail; +} + +/** Get available receive fifo count */ +static int32_t dw_spi_get_rxavail(DW_SPI_CTRL *spi_ctrl_ptr) +{ + int32_t rx_avail = 0; + DW_SPI_REG *spi_reg_ptr = (DW_SPI_REG *)(spi_ctrl_ptr->dw_spi_regs); + +#if DW_SPI_CALC_FIFO_LEN_ENABLE + if (spi_ctrl_ptr->rx_fifo_len <= 1) { + if (dw_spi_getready(spi_reg_ptr) == 1) { + rx_avail = 1; + } else { + rx_avail = 0; + } + } else +#endif + { + rx_avail = spi_reg_ptr->RXFLR; + } + return rx_avail; +} + +static uint32_t dw_spi_tx_max(DW_SPI_CTRL *spi_ctrl_ptr) +{ + uint32_t tx_left, tx_room; + DW_SPI_TRANSFER *xfer = &(spi_ctrl_ptr->dw_xfer); + + tx_left = (xfer->xfer_len - xfer->tx_idx) / xfer->nbytes; + tx_room = dw_spi_get_txavail(spi_ctrl_ptr); + + return (tx_left < tx_room) ? tx_left : tx_room; +} + +static uint32_t dw_spi_rx_max(DW_SPI_CTRL *spi_ctrl_ptr) +{ + uint32_t rx_left, rx_room; + DW_SPI_TRANSFER *xfer = &(spi_ctrl_ptr->dw_xfer); + + rx_left = (xfer->xfer_len - xfer->rx_idx) / xfer->nbytes; + rx_room = dw_spi_get_rxavail(spi_ctrl_ptr); + + return (rx_left < rx_room) ? rx_left : rx_room; +} + +Inline int32_t dw_spi_rx_end(DW_SPI_CTRL *spi_ctrl_ptr) +{ + DW_SPI_TRANSFER *xfer = &(spi_ctrl_ptr->dw_xfer); + + return (xfer->rx_idx >= xfer->xfer_len); +} + +Inline int32_t dw_spi_tx_end(DW_SPI_CTRL *spi_ctrl_ptr) +{ + DW_SPI_TRANSFER *xfer = &(spi_ctrl_ptr->dw_xfer); + + return (xfer->tx_idx >= xfer->xfer_len); +} + +/** 1 for end, 0 for not end */ +Inline int32_t dw_spi_xfer_end(DW_SPI_CTRL *spi_ctrl_ptr) +{ + return (dw_spi_tx_end(spi_ctrl_ptr) && dw_spi_rx_end(spi_ctrl_ptr)); +} + +static int32_t dw_spi_writer(DEV_SPI_INFO *spi_info_ptr) +{ + DW_SPI_CTRL *spi_ctrl_ptr = (DW_SPI_CTRL_PTR)(spi_info_ptr->spi_ctrl); + DW_SPI_TRANSFER *dw_xfer = &(spi_ctrl_ptr->dw_xfer); + DW_SPI_REG *spi_reg_ptr = (DW_SPI_REG *)(spi_ctrl_ptr->dw_spi_regs); + uint32_t tx_max = dw_spi_tx_max(spi_ctrl_ptr); + int32_t tx_w; + uint32_t tx_cnt = tx_max; + + if (dw_xfer->tx_xfer == NULL) { + return 0; + } + while (tx_max) { + if (dw_xfer->tx_xfer->tx_idx >= dw_xfer->tx_xfer->tot_len) { + dw_xfer->tx_xfer = dw_xfer->tx_xfer->next; + if (dw_xfer->tx_xfer == NULL) { + break; + } + } + if ( (dw_xfer->tx_xfer->tx_idx >= dw_xfer->tx_xfer->tx_ofs) \ + && (dw_xfer->tx_xfer->tx_idx < dw_xfer->tx_xfer->tx_totlen)) { + if (dw_xfer->nbytes == 1) { + tx_w = (int32_t)(*(int8_t *)(dw_xfer->tx_xfer->tx_buf)); + } else { + tx_w = (int32_t)(*(int16_t *)(dw_xfer->tx_xfer->tx_buf)); + } + dw_xfer->tx_xfer->tx_buf += dw_xfer->nbytes; + } else { + tx_w = spi_info_ptr->dummy; + } + dw_spi_putdata(spi_reg_ptr, tx_w); + dw_xfer->tx_xfer->tx_idx += dw_xfer->nbytes; + dw_xfer->tx_idx += dw_xfer->nbytes; + tx_max --; + } + return ((tx_cnt-tx_max) * dw_xfer->nbytes); +} + +static int32_t dw_spi_reader(DEV_SPI_INFO *spi_info_ptr) +{ + DW_SPI_CTRL *spi_ctrl_ptr = (DW_SPI_CTRL_PTR)(spi_info_ptr->spi_ctrl); + DW_SPI_TRANSFER *dw_xfer = &(spi_ctrl_ptr->dw_xfer); + DW_SPI_REG *spi_reg_ptr = (DW_SPI_REG *)(spi_ctrl_ptr->dw_spi_regs); + uint32_t rx_max = dw_spi_rx_max(spi_ctrl_ptr); + int32_t rx_w; + uint32_t rx_cnt = rx_max; + + if (dw_xfer->rx_xfer == NULL) { + return 0; + } + while (rx_max) { + if (dw_xfer->rx_xfer->rx_idx >= dw_xfer->rx_xfer->tot_len) { + dw_xfer->rx_xfer = dw_xfer->rx_xfer->next; + if (dw_xfer->rx_xfer == NULL) { + break; + } + } + rx_w = dw_spi_getdata(spi_reg_ptr); + if ( (dw_xfer->rx_xfer->rx_idx >= dw_xfer->rx_xfer->rx_ofs) \ + && (dw_xfer->rx_xfer->rx_idx < dw_xfer->rx_xfer->rx_totlen) ) { + if (dw_xfer->nbytes == 1) { + *(int8_t *)(dw_xfer->rx_xfer->rx_buf) = rx_w; + } else { + *(int16_t *)(dw_xfer->rx_xfer->rx_buf) = rx_w; + } + dw_xfer->rx_xfer->rx_buf += dw_xfer->nbytes; + } + dw_xfer->rx_xfer->rx_idx += dw_xfer->nbytes; + dw_xfer->rx_idx += dw_xfer->nbytes; + rx_max --; + } + return ((rx_cnt-rx_max) * dw_xfer->nbytes); +} + +Inline uint32_t dw_spi_nbytes(uint32_t dfs) +{ + uint32_t nbytes = 1; + + if (dfs > 8) nbytes = 2; + return nbytes; +} + +static void dw_spi_init_transfer(DW_SPI_CTRL *spi_ctrl_ptr, DEV_SPI_TRANSFER *xfer, uint32_t dfs) +{ + DW_SPI_TRANSFER *dw_xfer= &(spi_ctrl_ptr->dw_xfer); + uint32_t tot_len = 0; + + dw_xfer->tx_xfer = xfer; + dw_xfer->rx_xfer = xfer; + dw_xfer->tx_idx = 0; + dw_xfer->rx_idx = 0; + dw_xfer->nbytes = dw_spi_nbytes(dfs); + + /** Calculate all transfer length */ + while (xfer) { + DEV_SPI_XFER_INIT(xfer); + tot_len += xfer->tot_len; + xfer = xfer->next; + } + dw_xfer->xfer_len = tot_len; +} + +/* Check buffer align status, 0 for aligned, -1 for not-aligned */ +static int32_t dw_spi_chk_xfer_aligned(DEV_SPI_TRANSFER *xfer, uint32_t dfs) +{ + uint32_t align_bytes = 1; + if (xfer == NULL) return -1; + + if (dfs > 8) { + align_bytes = 2; + } else { + return 0; + } + + while (xfer) { + /* check tx buffer align status */ + if (xfer->tx_len != 0) { + if (xfer->tx_len % align_bytes) return -1; + if (xfer->tx_ofs % align_bytes) return -1; + if (!CHECK_ALIGN_BYTES(xfer->tx_buf, align_bytes)) return -1; + } + /* check tx buffer align status */ + if (xfer->rx_len != 0) { + if (xfer->rx_len % align_bytes) return -1; + if (xfer->rx_ofs % align_bytes) return -1; + if (!CHECK_ALIGN_BYTES(xfer->rx_buf, align_bytes)) return -1; + } + xfer = xfer->next; + } + return 0; +} + +static uint32_t dw_spi_poll_transfer(DEV_SPI_INFO *spi_info_ptr) +{ + uint32_t len = 0; + DW_SPI_CTRL *spi_ctrl_ptr = (DW_SPI_CTRL_PTR)(spi_info_ptr->spi_ctrl); + + spi_info_ptr->status |= DEV_IN_XFER; + while (!dw_spi_xfer_end(spi_ctrl_ptr)) { + len += dw_spi_writer(spi_info_ptr); + len += dw_spi_reader(spi_info_ptr); + } + spi_info_ptr->status &= ~DEV_IN_XFER; + + return len>>1; +} + +/** @} */ + +/** + * \brief open a designware spi device + * \param[in] spi_obj spi object pointer + * \param[in] mode spi working mode (master or slave) + * \param[in] param parameter, for master, param is the freq, for slave, param is dfs + * \retval E_OK Open successfully without any issues + * \retval E_OPNED If device was opened before with different parameters, + * then just increase the \ref dev_spi_info::opn_cnt "opn_cnt" and return \ref E_OPNED + * \retval E_OBJ Device object is not valid + * \retval E_SYS Device is opened for different mode before, if you want to open it with different mode, you need to fully close it first. + * \retval E_PAR Parameter is not valid + * \retval E_NOSPT Open settings are not supported + */ +int32_t dw_spi_open (DEV_SPI *spi_obj, uint32_t mode, uint32_t param) +{ + int32_t ercd = E_OK; + uint32_t param2check; + uint32_t clk_mode, dfs_val; + uint32_t support_modes; + DEV_SPI_INFO *spi_info_ptr = &(spi_obj->spi_info); + + /* START ERROR CHECK */ + VALID_CHK_SPI_INFO_OBJECT(spi_info_ptr); + DW_SPI_CHECK_EXP((mode==DEV_MASTER_MODE)||(mode==DEV_SLAVE_MODE), E_PAR); + if (mode == DEV_SLAVE_MODE) { /* clock mode should be in the enum structure */ + DW_SPI_CHECK_EXP((param>=SPI_CPOL_0_CPHA_0) && (param<=SPI_CPOL_1_CPHA_1), E_PAR); + } else { /* frequence should > 0 */ + DW_SPI_CHECK_EXP(param>0, E_PAR); + } + /* END OF ERROR CHECK */ + + DW_SPI_CTRL *spi_ctrl_ptr = (DW_SPI_CTRL_PTR)(spi_info_ptr->spi_ctrl); + + /* Check supported modes, master or slave */ + support_modes = spi_ctrl_ptr->support_modes; + DW_SPI_CHECK_EXP( (((support_modes)&DW_SPI_MASTER_SUPPORTED)&&(mode == DEV_MASTER_MODE)) || \ + (((support_modes)&DW_SPI_SLAVE_SUPPORTED)&&(mode == DEV_SLAVE_MODE)), E_NOSPT); + + /** Check opened before use case */ + if (spi_info_ptr->opn_cnt > 0) { + if (mode != spi_info_ptr->mode) { + /* current working mode is different from passing mode */ + return E_SYS; + } + if (mode == DEV_MASTER_MODE) { /* param is freq when as master */ + param2check = spi_info_ptr->freq; + } else { /* param is clk_mode when as slave */ + param2check = spi_info_ptr->clk_mode; + } + spi_info_ptr->opn_cnt ++; + if (param != param2check) { /* open with different speed mode */ + return E_OPNED; + } else { + return E_OK; + } + } + /* auto increase open count */ + spi_info_ptr->opn_cnt ++; + + /* Do FIFO Length get before init */ +#if DW_SPI_CALC_FIFO_LEN_ENABLE + spi_ctrl_ptr->tx_fifo_len = dw_spi_get_txfifo_len(spi_ctrl_ptr->dw_spi_regs); + spi_ctrl_ptr->rx_fifo_len = dw_spi_get_rxfifo_len(spi_ctrl_ptr->dw_spi_regs); +#endif + /* hardware init */ + spi_info_ptr->mode = mode; + clk_mode = SPI_CLK_MODE_DEFAULT; + dfs_val = SPI_DFS_DEFAULT; + if (mode == DEV_SLAVE_MODE) { + clk_mode = param; + } + spi_info_ptr->dfs = dfs_val; + spi_info_ptr->clk_mode = clk_mode; + dw_spi_hw_init(spi_ctrl_ptr, clk_mode, dfs_val); + if (mode == DEV_MASTER_MODE) { /* Deselect all slaves, and set frequence */ + dw_spi_deselect_slave(spi_ctrl_ptr->dw_spi_regs, 0); + dw_spi_set_freq(spi_ctrl_ptr, param); + spi_info_ptr->freq = param; + } + + spi_info_ptr->status = DEV_ENABLED; + spi_info_ptr->extra = NULL; + spi_info_ptr->slave = SPI_SLAVE_NOT_SELECTED; + spi_info_ptr->dummy = 0xff; + + spi_ctrl_ptr->int_status = 0; + dw_spi_init_transfer(spi_ctrl_ptr, NULL, dfs_val); + + /** install spi interrupt into system */ + dw_spi_disable_interrupt(spi_info_ptr); + int_handler_install(spi_ctrl_ptr->intno, spi_ctrl_ptr->dw_spi_int_handler); + memset(&(spi_info_ptr->xfer), 0, sizeof(DEV_SPI_TRANSFER)); + memset(&(spi_info_ptr->spi_cbs), 0, sizeof(DEV_SPI_CBS)); + +error_exit: + return ercd; +} + +/** + * \brief close a DesignWare SPI device + * \param[in] spi_obj spi object pointer + * \retval E_OK Close successfully without any issues(including scenario that device is already closed) + * \retval E_OPNED Device is still opened, the device \ref dev_spi_info::opn_cnt "opn_cnt" decreased by 1 + * \retval E_OBJ Device object is not valid + */ +int32_t dw_spi_close (DEV_SPI *spi_obj) +{ + int32_t ercd = E_OK; + DEV_SPI_INFO *spi_info_ptr = &(spi_obj->spi_info); + + /* START ERROR CHECK */ + VALID_CHK_SPI_INFO_OBJECT(spi_info_ptr); + DW_SPI_CHECK_EXP(spi_info_ptr->opn_cnt > 0, E_OK); + /* END OF ERROR CHECK */ + + spi_info_ptr->opn_cnt --; + if (spi_info_ptr->opn_cnt == 0) { + DW_SPI_CTRL *spi_ctrl_ptr = (DW_SPI_CTRL *)(spi_info_ptr->spi_ctrl); + + dw_spi_disable_interrupt(spi_info_ptr); + dw_spi_abort_tx(spi_obj); + dw_spi_abort_rx(spi_obj); + memset(&(spi_info_ptr->xfer), 0, sizeof(DEV_SPI_TRANSFER)); + memset(&(spi_info_ptr->spi_cbs), 0, sizeof(DEV_SPI_CBS)); + memset(&(spi_ctrl_ptr->dw_xfer), 0, sizeof(DW_SPI_TRANSFER)); + dw_spi_disable_device(spi_info_ptr); + spi_info_ptr->status = DEV_DISABLED; + spi_info_ptr->extra = NULL; + } else { + ercd = E_OPNED; + } + +error_exit: + return ercd; +} + +/** + * \brief control spi by ctrl command + * \param[in] spi_obj spi object pointer + * \param[in] ctrl_cmd control command code to do specific spi work + * \param[in,out] param parameters used to control spi or return something + * \retval E_OK Control device successfully + * \retval E_CLSED Device is not opened + * \retval E_OBJ Device object is not valid or not exists + * \retval E_PAR Parameter is not valid for current control command + * \retval E_SYS Control device failed, due to hardware issues, such as device is disabled + * \retval E_CTX Control device failed, due to different reasons like in transfer state + * \retval E_NOSPT Control command is not supported or not valid + */ +int32_t dw_spi_control (DEV_SPI *spi_obj, uint32_t ctrl_cmd, void *param) +{ + int32_t ercd = E_OK; + DEV_SPI_INFO *spi_info_ptr = &(spi_obj->spi_info); + + /* START ERROR CHECK */ + VALID_CHK_SPI_INFO_OBJECT(spi_info_ptr); + DW_SPI_CHECK_EXP(spi_info_ptr->opn_cnt > 0, E_CLSED); + /* END OF ERROR CHECK */ + + uint32_t val32; /** to receive unsigned int value */ + DEV_BUFFER *devbuf; + + DW_SPI_CTRL *spi_ctrl_ptr = (DW_SPI_CTRL *)(spi_info_ptr->spi_ctrl); + DW_SPI_REG *spi_reg_ptr = (DW_SPI_REG *)(spi_ctrl_ptr->dw_spi_regs); + DEV_SPI_TRANSFER *spi_xfer = &(spi_info_ptr->xfer); + + /* check whether current device is disabled */ + if ((spi_info_ptr->status & DEV_ENABLED) == 0) { + /** When device is disabled, + * only SPI_CMD_ENA_DEV, SPI_CMD_DIS_DEV, SPI_CMD_GET_STATUS, SPI_CMD_RESET + * are available, other commands will return E_SYS + */ + if ((ctrl_cmd != SPI_CMD_ENA_DEV) && \ + (ctrl_cmd != SPI_CMD_DIS_DEV) && \ + (ctrl_cmd != SPI_CMD_GET_STATUS) && \ + (ctrl_cmd != SPI_CMD_RESET) ) { + return E_SYS; + } + } + + switch (ctrl_cmd) { + /* Commmon commands for both master and slave mode */ + case SPI_CMD_GET_STATUS: + DW_SPI_CHECK_EXP((param!=NULL) && CHECK_ALIGN_4BYTES(param), E_PAR); + *((int32_t *)param) = spi_info_ptr->status; + break; + case SPI_CMD_SET_CLK_MODE: + DW_SPI_CHECK_EXP((spi_info_ptr->status & DEV_IN_XFER) == 0, E_CTX); + val32 = (uint32_t)param; + DW_SPI_CHECK_EXP((val32>=SPI_CPOL_0_CPHA_0) && (val32<=SPI_CPOL_1_CPHA_1), E_PAR); + if (dw_spi_set_clockmode(spi_reg_ptr, val32) == 0) { + spi_info_ptr->clk_mode = val32; + } else { + ercd = E_SYS; + } + break; + case SPI_CMD_ENA_DEV: + dw_spi_enable_device(spi_info_ptr); + break; + case SPI_CMD_DIS_DEV: + dw_spi_disable_device(spi_info_ptr); + break; + case SPI_CMD_RESET: + dw_spi_reset_device(spi_info_ptr); + break; + case SPI_CMD_FLUSH_TX: + DW_SPI_CHECK_EXP((spi_info_ptr->status & DEV_IN_XFER) == 0, E_CTX); + dw_spi_flush_tx(spi_reg_ptr); + break; + case SPI_CMD_FLUSH_RX: + DW_SPI_CHECK_EXP((spi_info_ptr->status & DEV_IN_XFER) == 0, E_CTX); + dw_spi_flush_rx(spi_reg_ptr); + break; + case SPI_CMD_SET_DFS: + DW_SPI_CHECK_EXP((spi_info_ptr->status & DEV_IN_XFER) == 0, E_CTX); + val32 = (uint32_t)param; + DW_SPI_CHECK_EXP(val32>0, E_PAR); + if (dw_spi_set_dfs(spi_reg_ptr, val32) == 0) { + spi_info_ptr->dfs = val32; + } else { + ercd = E_SYS; + } + break; + case SPI_CMD_SET_DUMMY_DATA: + val32 = (uint32_t)param; + spi_info_ptr->dummy = val32; + break; + case SPI_CMD_GET_RXAVAIL: /* Notice in bytes unit */ + DW_SPI_CHECK_EXP((param!=NULL) && CHECK_ALIGN_4BYTES(param), E_PAR); + *((int32_t *)param) = dw_spi_get_rxavail(spi_ctrl_ptr) * dw_spi_nbytes(spi_info_ptr->dfs); + break; + case SPI_CMD_GET_TXAVAIL: /* Notice in bytes unit */ + DW_SPI_CHECK_EXP((param!=NULL) && CHECK_ALIGN_4BYTES(param), E_PAR); + *((int32_t *)param) = dw_spi_get_txavail(spi_ctrl_ptr) * dw_spi_nbytes(spi_info_ptr->dfs); + break; + case SPI_CMD_SET_TXCB: + DW_SPI_CHECK_EXP(CHECK_ALIGN_4BYTES(param), E_PAR); + spi_info_ptr->spi_cbs.tx_cb = param; + break; + case SPI_CMD_SET_RXCB: + DW_SPI_CHECK_EXP(CHECK_ALIGN_4BYTES(param), E_PAR); + spi_info_ptr->spi_cbs.rx_cb = param; + break; + case SPI_CMD_SET_XFERCB: + DW_SPI_CHECK_EXP(CHECK_ALIGN_4BYTES(param), E_PAR); + spi_info_ptr->spi_cbs.xfer_cb = param; + break; + case SPI_CMD_SET_ERRCB: + DW_SPI_CHECK_EXP(CHECK_ALIGN_4BYTES(param), E_PAR); + spi_info_ptr->spi_cbs.err_cb = param; + break; + case SPI_CMD_ABORT_TX: + ercd = dw_spi_abort_tx(spi_obj); + break; + case SPI_CMD_ABORT_RX: + ercd = dw_spi_abort_rx(spi_obj); + break; + case SPI_CMD_ABORT_XFER: + ercd = dw_spi_abort_xfer(spi_obj); + break; + case SPI_CMD_SET_TXINT: + val32 = (uint32_t)param; + if (val32 == 0) { + ercd = dw_spi_dis_cbr(spi_info_ptr, DW_SPI_RDY_SND); + } else { + ercd = dw_spi_ena_cbr(spi_info_ptr, DW_SPI_RDY_SND); + } + break; + case SPI_CMD_SET_RXINT: + val32 = (uint32_t)param; + if (val32 == 0) { + ercd = dw_spi_dis_cbr(spi_info_ptr, DW_SPI_RDY_RCV); + } else { + ercd = dw_spi_ena_cbr(spi_info_ptr, DW_SPI_RDY_RCV); + } + break; + case SPI_CMD_SET_TXINT_BUF: + DW_SPI_CHECK_EXP(CHECK_ALIGN_4BYTES(param), E_PAR); + DW_SPI_CHECK_EXP((spi_info_ptr->status & DEV_IN_XFER) == 0, E_CTX); + if (param != NULL) { + devbuf = (DEV_BUFFER *)param; + DEV_SPI_XFER_SET_TXBUF(spi_xfer, devbuf->buf, 0, devbuf->len); + DEV_SPI_XFER_SET_RXBUF(spi_xfer, NULL, devbuf->len, 0); + DEV_SPI_XFER_SET_NEXT(spi_xfer, NULL); + DW_SPI_CHECK_EXP(dw_spi_chk_xfer_aligned(spi_xfer, spi_info_ptr->dfs) == 0, E_PAR); + dw_spi_init_transfer(spi_ctrl_ptr, spi_xfer, spi_info_ptr->dfs); + } else { + DEV_SPI_XFER_SET_TXBUF(spi_xfer, NULL, 0, 0); + DEV_SPI_XFER_SET_RXBUF(spi_xfer, NULL, 0, 0); + DEV_SPI_XFER_SET_NEXT(spi_xfer, NULL); + dw_spi_init_transfer(spi_ctrl_ptr, NULL, spi_info_ptr->dfs); + } + break; + case SPI_CMD_SET_RXINT_BUF: + DW_SPI_CHECK_EXP(CHECK_ALIGN_4BYTES(param), E_PAR); + DW_SPI_CHECK_EXP((spi_info_ptr->status & DEV_IN_XFER) == 0, E_CTX); + if (param != NULL) { + devbuf = (DEV_BUFFER *)param; + DEV_SPI_XFER_SET_TXBUF(spi_xfer, NULL, devbuf->len, 0); + DEV_SPI_XFER_SET_RXBUF(spi_xfer, devbuf->buf, 0, devbuf->len); + DEV_SPI_XFER_SET_NEXT(spi_xfer, NULL); + /* Check transfer align */ + DW_SPI_CHECK_EXP(dw_spi_chk_xfer_aligned(spi_xfer, spi_info_ptr->dfs) == 0, E_PAR); + dw_spi_init_transfer(spi_ctrl_ptr, spi_xfer, spi_info_ptr->dfs); + } else { + DEV_SPI_XFER_SET_TXBUF(spi_xfer, NULL, 0, 0); + DEV_SPI_XFER_SET_RXBUF(spi_xfer, NULL, 0, 0); + DEV_SPI_XFER_SET_NEXT(spi_xfer, NULL); + dw_spi_init_transfer(spi_ctrl_ptr, NULL, spi_info_ptr->dfs); + } + break; + case SPI_CMD_TRANSFER_POLLING: + DW_SPI_CHECK_EXP(CHECK_ALIGN_4BYTES(param), E_PAR); + DW_SPI_CHECK_EXP((spi_info_ptr->status & DEV_IN_XFER) == 0, E_CTX); + if (param != NULL) { + /* Check transfer align */ + DW_SPI_CHECK_EXP(dw_spi_chk_xfer_aligned((DEV_SPI_TRANSFER *)param, spi_info_ptr->dfs) == 0, E_PAR); + *spi_xfer = *((DEV_SPI_TRANSFER *)param); + dw_spi_init_transfer(spi_ctrl_ptr, spi_xfer, spi_info_ptr->dfs); + /* Transfer data by poll */ + dw_spi_poll_transfer(spi_info_ptr); + } else { + ercd = E_PAR; + } + break; + case SPI_CMD_TRANSFER_INT: + DW_SPI_CHECK_EXP(CHECK_ALIGN_4BYTES(param), E_PAR); + if (param != NULL) { + DW_SPI_CHECK_EXP((spi_info_ptr->status & DEV_IN_XFER) == 0, E_CTX); + /* Check transfer align */ + DW_SPI_CHECK_EXP(dw_spi_chk_xfer_aligned((DEV_SPI_TRANSFER *)param, spi_info_ptr->dfs) == 0, E_PAR); + *spi_xfer = *((DEV_SPI_TRANSFER *)param); + dw_spi_init_transfer(spi_ctrl_ptr, spi_xfer, spi_info_ptr->dfs); + /* Transfer data by interrupt */ + ercd = dw_spi_ena_cbr(spi_info_ptr, DW_SPI_RDY_XFER); + } else { + ercd = dw_spi_dis_cbr(spi_info_ptr, DW_SPI_RDY_XFER); + } + break; + + /* Master mode only commands */ + case SPI_CMD_MST_SET_FREQ: + DW_SPI_CHECK_EXP(spi_info_ptr->mode == DEV_MASTER_MODE, E_NOSPT); + DW_SPI_CHECK_EXP((spi_info_ptr->status & DEV_IN_XFER) == 0, E_CTX); + val32 = (uint32_t)param; + DW_SPI_CHECK_EXP(val32>0, E_PAR); + dw_spi_set_freq(spi_ctrl_ptr, val32); + spi_info_ptr->freq = val32; + break; + case SPI_CMD_MST_SEL_DEV: + DW_SPI_CHECK_EXP(spi_info_ptr->mode == DEV_MASTER_MODE, E_NOSPT); + DW_SPI_CHECK_EXP((spi_info_ptr->status & DEV_IN_XFER) == 0, E_CTX); + val32 = (uint32_t)param; + if (dw_spi_select_slave(spi_reg_ptr, val32) == 0) { + spi_info_ptr->slave = val32; + } else { + ercd = E_SYS; + } + break; + case SPI_CMD_MST_DSEL_DEV: + DW_SPI_CHECK_EXP(spi_info_ptr->mode == DEV_MASTER_MODE, E_NOSPT); + DW_SPI_CHECK_EXP((spi_info_ptr->status & DEV_IN_XFER) == 0, E_CTX); + val32 = (uint32_t)param; + if (dw_spi_deselect_slave(spi_reg_ptr, val32) == 0) { + spi_info_ptr->slave = SPI_SLAVE_NOT_SELECTED; + } else { + ercd = E_SYS; + } + break; + + /* Slave mode only commands */ + + + default: + ercd = E_NOSPT; + break; + } + +error_exit: + return ercd; +} + +/** + * \brief send data through DesignWare SPI + * \param[in] spi_obj spi object pointer + * \param[in] data pointer to data need to send by spi + * \param[in] len length of data to be sent + * \retval >0 Byte count that was successfully sent for poll method + * \retval E_OBJ Device object is not valid or not exists + * \retval E_PAR Parameter is not valid + * \retval E_CTX Device is still in transfer state + * \retval E_SYS Can't write data to hardware due to hardware issues, such as device is disabled + */ +int32_t dw_spi_write (DEV_SPI *spi_obj, const void *data, uint32_t len) +{ + int32_t ercd = E_OK; + DEV_SPI_INFO *spi_info_ptr = &(spi_obj->spi_info); + + /* START ERROR CHECK */ + VALID_CHK_SPI_INFO_OBJECT(spi_info_ptr); + DW_SPI_CHECK_EXP(spi_info_ptr->opn_cnt > 0, E_CLSED); + DW_SPI_CHECK_EXP(spi_info_ptr->status & DEV_ENABLED, E_SYS); + DW_SPI_CHECK_EXP((spi_info_ptr->status & DEV_IN_XFER) == 0, E_CTX); + DW_SPI_CHECK_EXP(data!=NULL, E_PAR); + DW_SPI_CHECK_EXP(len>0, E_PAR); + /* END OF ERROR CHECK */ + + DW_SPI_CTRL *spi_ctrl_ptr = (DW_SPI_CTRL_PTR)(spi_info_ptr->spi_ctrl); + DEV_SPI_TRANSFER spi_xfer; + + /* Master and Slave transmit */ + DEV_SPI_XFER_SET_TXBUF(&spi_xfer, data, 0, len); + DEV_SPI_XFER_SET_RXBUF(&spi_xfer, NULL, len, 0); + DEV_SPI_XFER_SET_NEXT(&spi_xfer, NULL); + + /* Check transfer align */ + DW_SPI_CHECK_EXP(dw_spi_chk_xfer_aligned(&spi_xfer, spi_info_ptr->dfs) == 0, E_PAR); + + dw_spi_init_transfer(spi_ctrl_ptr, &spi_xfer, spi_info_ptr->dfs); + + ercd = dw_spi_poll_transfer(spi_info_ptr); + +error_exit: + return ercd; +} + +/** + * \brief read data through DesignWare SPI + * \param[in] spi_info_ptr spi information structure pointer + * \param[out] data data that need to read (data must be char type) + * \param[in] len data count need to read + * \retval >=0 data have been read + * \retval E_PAR arguments passed was wrong + * \retval E_OBJ spi has something error, nothing can be done + * \retval E_CLSED spi was closed, not available for control + * \retval <0 other error code not defined here + */ +int32_t dw_spi_read (DEV_SPI *spi_obj, void *data, uint32_t len) +{ + int32_t ercd = E_OK; + DEV_SPI_INFO *spi_info_ptr = &(spi_obj->spi_info); + + /* START ERROR CHECK */ + VALID_CHK_SPI_INFO_OBJECT(spi_info_ptr); + DW_SPI_CHECK_EXP(spi_info_ptr->opn_cnt > 0, E_CLSED); + DW_SPI_CHECK_EXP(spi_info_ptr->status & DEV_ENABLED, E_SYS); + DW_SPI_CHECK_EXP((spi_info_ptr->status & DEV_IN_XFER) == 0, E_CTX); + DW_SPI_CHECK_EXP(data!=NULL, E_PAR); + DW_SPI_CHECK_EXP(len>0, E_PAR); + /* END OF ERROR CHECK */ + + DW_SPI_CTRL *spi_ctrl_ptr = (DW_SPI_CTRL_PTR)(spi_info_ptr->spi_ctrl); + DEV_SPI_TRANSFER spi_xfer; + + /* Master and Slave transmit */ + DEV_SPI_XFER_SET_TXBUF(&spi_xfer, NULL, len, 0); + DEV_SPI_XFER_SET_RXBUF(&spi_xfer, data, 0, len); + DEV_SPI_XFER_SET_NEXT(&spi_xfer, NULL); + + /* Check transfer align */ + DW_SPI_CHECK_EXP(dw_spi_chk_xfer_aligned(&spi_xfer, spi_info_ptr->dfs) == 0, E_PAR); + + dw_spi_init_transfer(spi_ctrl_ptr, &spi_xfer, spi_info_ptr->dfs); + + ercd = dw_spi_poll_transfer(spi_info_ptr); + +error_exit: + return ercd; +} + +/** + * \brief DesignWare SPI interrupt processing routine + * \param[in] spi_info_ptr DEV_SPI_INFO *spi_info_ptr + * \param[in] ptr extra information + */ +void dw_spi_isr(DEV_SPI *spi_obj, void *ptr) +{ + int32_t ercd = E_OK; + DEV_SPI_INFO *spi_info_ptr = &(spi_obj->spi_info); + + /* START ERROR CHECK */ + VALID_CHK_SPI_INFO_OBJECT(spi_info_ptr); + /* END OF ERROR CHECK */ + + DW_SPI_CTRL *spi_ctrl_ptr = (DW_SPI_CTRL_PTR)(spi_info_ptr->spi_ctrl); + DW_SPI_REG *spi_reg_ptr = (DW_SPI_REG *)(spi_ctrl_ptr->dw_spi_regs); + + uint32_t isr_status; + + isr_status = spi_reg_ptr->ISR; + + if (!isr_status) return; + if (spi_ctrl_ptr->dw_xfer.xfer_len == 0) { + dw_spi_disable_interrupt(spi_info_ptr); + } else { + if (isr_status & (DW_SPI_IMR_TXOIM|DW_SPI_IMR_RXOIM|DW_SPI_IMR_RXUIM)) { + dw_spi_clear_interrupt_all(spi_reg_ptr); + dw_spi_disable_interrupt(spi_info_ptr); + if (spi_info_ptr->spi_cbs.err_cb) { + spi_info_ptr->spi_cbs.err_cb(spi_obj); + } + memset(&(spi_ctrl_ptr->dw_xfer), 0, sizeof(DW_SPI_TRANSFER)); + } + dw_spi_reader(spi_info_ptr); + if (isr_status & DW_SPI_IMR_TXEIM) { + dw_spi_writer(spi_info_ptr); + } + if (dw_spi_xfer_end(spi_ctrl_ptr)) { + if ((spi_info_ptr->status & DW_SPI_IN_XFER) == DW_SPI_IN_TX) { + dw_spi_dis_cbr(spi_info_ptr, DW_SPI_RDY_SND); + if (spi_info_ptr->spi_cbs.tx_cb) { + spi_info_ptr->spi_cbs.tx_cb(spi_obj); + } + } else if ((spi_info_ptr->status & DW_SPI_IN_XFER) == DW_SPI_IN_RX) { + dw_spi_dis_cbr(spi_info_ptr, DW_SPI_RDY_RCV); + if (spi_info_ptr->spi_cbs.rx_cb) { + spi_info_ptr->spi_cbs.rx_cb(spi_obj); + } + } else if ((spi_info_ptr->status & DW_SPI_IN_XFER) == DW_SPI_IN_XFER) { + dw_spi_dis_cbr(spi_info_ptr, DW_SPI_RDY_XFER); + if (spi_info_ptr->spi_cbs.xfer_cb) { + spi_info_ptr->spi_cbs.xfer_cb(spi_obj); + } + } else { + dw_spi_disable_interrupt(spi_info_ptr); + } + memset(&(spi_ctrl_ptr->dw_xfer), 0, sizeof(DW_SPI_TRANSFER)); + } + } + +error_exit: + return; +} +/** @} */ /* DEVICE_DW_SPI_IMPLEMENT */ + +/** @} */ /* DEVICE_DW_SPI */ diff --git a/hw/mcu/arc/src/ext/sdk/device/designware/spi/dw_spi.h b/hw/mcu/arc/src/ext/sdk/device/designware/spi/dw_spi.h new file mode 100644 index 000000000..ef2faa90e --- /dev/null +++ b/hw/mcu/arc/src/ext/sdk/device/designware/spi/dw_spi.h @@ -0,0 +1,190 @@ +/* ------------------------------------------ + * Copyright (c) 2017, Synopsys, Inc. All rights reserved. + + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + + * 1) Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + + * 2) 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. + + * 3) Neither the name of the Synopsys, Inc., nor the names of its contributors may + * be used to endorse or promote products derived from this software without + * specific prior written permission. + + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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. + * + * \version 2017.03 + * \date 2014-06-25 + * \author Huaqi Fang(Huaqi.Fang@synopsys.com) +--------------------------------------------- */ + +/** + * \file + * \brief DesignWare SPI driver header file + * \ingroup DEVICE_DW_SPI + */ + +#ifndef _DEVICE_DW_SPI_H_ +#define _DEVICE_DW_SPI_H_ + +#include "device/device_hal/inc/dev_spi.h" + +/** + * if this header file is included, + * will indicate that this designware spi device + * is used + */ +#define DEVICE_USE_DESIGNWARE_SPI + +#define DW_SPI_IN_FREE (0) /*!< Currently not in spi transfer */ +#define DW_SPI_IN_XFER (DEV_IN_TX|DEV_IN_RX|DEV_IN_XFER) /*!< Currently in spi transfer */ +#define DW_SPI_IN_TX (DEV_IN_TX|DEV_IN_XFER) /*!< Currently in spi tx */ +#define DW_SPI_IN_RX (DEV_IN_RX|DEV_IN_XFER) /*!< Currently in spi rx */ + +#define DW_SPI_GINT_DISABLED (0) /*!< designware interrupt disabled for control iic irq/fiq */ +#define DW_SPI_GINT_ENABLE (1<<0) /*!< designware interrupt enabled for control iic irq/fiq */ + +#define DW_SPI_MASTER_SUPPORTED (0x1) /*!< Support Designware SPI Master Mode */ +#define DW_SPI_SLAVE_SUPPORTED (0x2) /*!< Support Designware SPI Slave Mode */ +/*!< Support Designware SPI Both Master and Slave Mode */ +#define DW_SPI_BOTH_SUPPORTED (DW_SPI_MASTER_SUPPORTED|DW_SPI_SLAVE_SUPPORTED) + +/** + * \defgroup DEVICE_DW_SPI_REGSTRUCT DesignWare SPI Register Structure + * \ingroup DEVICE_DW_SPI + * \brief contains definitions of DesignWare SPI register structure. + * \details detailed description of DesignWare SPI register information + * @{ + */ +/** + * \brief DesignWare SPI register structure + * \details Detailed struct description of DesignWare SPI + * block register information, implementation of dev_spi_info::spi_regs + */ +typedef volatile struct dw_spi_reg +{ + /*!< Control Register */ + /*!< SPI Control Register 0 (0x0) */ + uint32_t CTRLR0; + /*!< SPI Control Register 1 (0x4) */ + uint32_t CTRLR1; + /*!< Enable Register */ + /*!< SPI Enable Register (0x8) */ + uint32_t SSIENR; + /*!< SPI Microwire Control Register (0xC) */ + uint32_t MWCR; + /*!< SPI Slave Enable Register (0x10) */ + uint32_t SER; + /*!< SPI Baud Rate Select Register (0x14) */ + uint32_t BAUDR; + /*!< TX and RX FIFO Control Register */ + /*!< SPI Transmit FIFO Threshold Level Register (0x18) */ + uint32_t TXFTLR; + /*!< SPI Receive FIFO Threshold Level Register (0x1C) */ + uint32_t RXFTLR; + /*!< SPI Transmit FIFO Level Register (0x20) */ + uint32_t TXFLR; + /*!< SPI Receive FIFO Level Register (0x24) */ + uint32_t RXFLR; + /*!< SPI Status Register (0x28) */ + uint32_t SR; + /*!< Interrupt Enable/Disable/Control Registers */ + /*!< SPI Interrupt Mask Register (0x2C) */ + uint32_t IMR; + /*!< SPI Interrupt Status Register (0x30) */ + uint32_t ISR; + /*!< SPI Raw Interrupt Status Register (0x34) */ + uint32_t RISR; + /*!< SPI Transmit FIFO Overflow Interrupt Clear Register (0x38) */ + uint32_t TXOICR; + /*!< SPI Receive FIFO Overflow Interrupt Clear Register (0x3C) */ + uint32_t RXOICR; + /*!< SPI Receive FIFO Underflow Interrupt Clear Register (0x40) */ + uint32_t RXUICR; + /*!< SPI Multi-Master Interrupt Clear Register (0x44) */ + uint32_t MSTICR; + /*!< SPI Interrupt Clear Register (0x48) */ + uint32_t ICR; + /*!< DMA Control Register (0x4C) */ + uint32_t DMACR; + /*!< DMA Transmit Data Level (0x50) */ + uint32_t DMATDLR; + /*!< DMA Receive Data Level (0x54) */ + uint32_t DMARDLR; + /*!< SPI Identification Register (0x58) */ + uint32_t IDR; + /*!< SPI CoreKit ID Register (Value after Reset : 0x3332322A) (0x5C) */ + uint32_t SSI_VER_ID; + /*!< Data Register */ + /*!< SPI DATA Register for both Read and Write (0x60) */ + uint32_t DATAREG; +} DW_SPI_REG, *DW_SPI_REG_PTR; +/** @} */ + +/** Designware SPI Message Transfer */ +typedef struct dw_spi_transfer { + uint32_t xfer_len; + uint32_t tx_idx; + uint32_t rx_idx; + uint32_t nbytes; + DEV_SPI_TRANSFER *tx_xfer; + DEV_SPI_TRANSFER *rx_xfer; +} DW_SPI_TRANSFER, *DW_SPI_TRANSFER_PTR; + +/** + * \brief DesignWare SPI control structure definition + * \details implement of dev_spi_info::dev_spi_info + */ +typedef struct dw_spi_ctrl { + DW_SPI_REG *dw_spi_regs; /*!< spi register */ + /* Variables which should be set during object implementation */ + uint32_t support_modes; /*!< supported spi modes */ + uint32_t intno; /*!< interrupt no */ + uint32_t dw_apb_bus_freq; /*!< spi ip apb bus frequency */ + uint32_t tx_fifo_len; /*!< transmit fifo length */ + uint32_t rx_fifo_len; /*!< receive fifo length */ + INT_HANDLER dw_spi_int_handler; /*!< spi interrupt handler */ + /* Variables which always change during iic operation */ + uint32_t int_status; /*!< iic interrupt status */ + DW_SPI_TRANSFER dw_xfer; /*!< designware spi transfer */ +} DW_SPI_CTRL, *DW_SPI_CTRL_PTR; + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \defgroup DEVICE_DW_SPI_FUNCDLR DesignWare SPI Function Declaration + * \ingroup DEVICE_DW_SPI + * \brief contains declarations of designware spi functions. + * \details This are only used in \ref dw_spi_obj.c + * @{ + */ +extern int32_t dw_spi_open (DEV_SPI *spi_obj, uint32_t mode, uint32_t param); +extern int32_t dw_spi_close (DEV_SPI *spi_obj); +extern int32_t dw_spi_control (DEV_SPI *spi_obj, uint32_t ctrl_cmd, void *param); +extern int32_t dw_spi_write (DEV_SPI *spi_obj, const void *data, uint32_t len); +extern int32_t dw_spi_read (DEV_SPI *spi_obj, void *data, uint32_t len); +extern void dw_spi_isr(DEV_SPI *spi_obj, void *ptr); +/** @} */ + +#ifdef __cplusplus +} +#endif + +/** @} */ + +#endif /* _DEVICE_DW_SPI_H_ */ diff --git a/hw/mcu/arc/src/ext/sdk/device/designware/spi/dw_spi_hal.h b/hw/mcu/arc/src/ext/sdk/device/designware/spi/dw_spi_hal.h new file mode 100644 index 000000000..b1a233c69 --- /dev/null +++ b/hw/mcu/arc/src/ext/sdk/device/designware/spi/dw_spi_hal.h @@ -0,0 +1,141 @@ +/* ------------------------------------------ + * Copyright (c) 2017, Synopsys, Inc. All rights reserved. + + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + + * 1) Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + + * 2) 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. + + * 3) Neither the name of the Synopsys, Inc., nor the names of its contributors may + * be used to endorse or promote products derived from this software without + * specific prior written permission. + + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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. + * + * \version 2017.03 + * \date 2014-06-25 + * \author Huaqi Fang(Huaqi.Fang@synopsys.com) +--------------------------------------------- */ + +/** + * \file + * \ingroup DEVICE_DW_SPI + * \brief DesignWare SPI driver hardware description related header file + * \details detailed hardware related definitions of DesignWare SPI driver + */ + +#ifndef _DEVICE_DW_SPI_HAL_H_ +#define _DEVICE_DW_SPI_HAL_H_ + +#include "device/designware/spi/dw_spi_hal_cfg.h" + +/* DW APB SPI bit definitions */ + +/** + * \name DesignWare SPI HAL CTRL0 Macros + * \brief DesignWare SPI hal ctrl0 macros, + * include dfs, scph, scppl, tmod, etc + * @{ + */ +#define DW_SPI_CTRLR0_DFS_MASK (0xf) + +#define DW_SPI_CTRLR0_SC_OFS (6) +#define DW_SPI_CTRLR0_SC_MASK (0xC0) +#define DW_SPI_CTRLR0_SCPH_HIGH (0x40) +#define DW_SPI_CTRLR0_SCPH_LOW (0) +#define DW_SPI_CTRLR0_SCPOL_HIGH (0x80) +#define DW_SPI_CTRLR0_SCPOL_LOW (0) + +#define DW_SPI_CTRLR0_TMOD_MASK (0x300) +#define DW_SPI_TMOD_TRANSMIT_RECEIVE (0) +#define DW_SPI_TMOD_TRANSMIT_ONLY (0x100) +#define DW_SPI_TMOD_RECEIVE_ONLY (0x200) +#define DW_SPI_TMOD_EEPROM_READ_ONLY (0x300) + +#define DW_SPI_CTRLR0_FRF_MOTOROLA (0x0) +#define DW_SPI_CTRLR0_FRF_TI (0x10) +#define DW_SPI_CTRLR0_FRF_MICROWIRE (0x20) + +#define DW_SPI_CTRLR0_SLV_OE_DISABLE (1<<10) +#define DW_SPI_CTRLR0_SLV_OE_ENABLE (0) + + +/** @} */ + +/** + * \name DesignWare SPI HAL ISR Flags + * \brief DesignWare SPI hal Interrupt Status Flags + * @{ + */ +#define DW_SPI_TX_OVERFLOW_ERROR (0x2) +#define DW_SPI_RX_UNDERFLOW_ERROR (0x4) +#define DW_SPI_RX_OVERFLOW_ERROR (0x8) + +#define DW_SPI_ISR_RX_FIFO_INT_MASK (0x10) +#define DW_SPI_ISR_TX_FIFO_INT_MASK (0x1) +#define DW_SPI_ISR_TX_OVERFLOW_INT_MASK (0x2) +#define DW_SPI_ISR_RX_UNDERFLOW_INT_MASK (0x4) +#define DW_SPI_ISR_RX_OVERFLOW_INT_MASK (0x8) +/** @} */ + +/** + * \name DesignWare SPI HAL SR Flags + * \brief DesignWare SPI hal Status Flags + * @{ + */ +#define DW_SPI_SR_DCOL (0x40) +#define DW_SPI_SR_TXE (0x20) +#define DW_SPI_SR_RFF (0x10) +#define DW_SPI_SR_RFNE (0x8) +#define DW_SPI_SR_TFE (0x4) +#define DW_SPI_SR_TFNF (0x2) +#define DW_SPI_SR_BUSY (0x1) +/** @} */ + +/** + * \name DesignWare SPI HAL SSI Enable Macros + * \brief DesignWare SPI hal ssi enable macros + * @{ + */ +/* Macros */ +#define DW_SPI_SSI_ENABLE (1) /*!< SSI Enable */ +#define DW_SPI_SSI_DISABLE (0) /*!< SSI Disable */ +/** @} */ + +/** + * \name DesignWare SPI HAL IMR Macros + * \brief DesignWare SPI hal interrupt mask macros + * @{ + */ +#define DW_SPI_IMR_MSTIM (0x20) /*!< Multi-Master Contention Interrupt Mask */ +#define DW_SPI_IMR_RXFIM (0x10) /*!< Receive FIFO Full Interrupt Mask */ +#define DW_SPI_IMR_RXOIM (0x08) /*!< Receive FIFO Overflow Interrupt Mask */ +#define DW_SPI_IMR_RXUIM (0x04) /*!< Receive FIFO Underflow Interrupt Mask */ +#define DW_SPI_IMR_TXOIM (0x02) /*!< Transmit FIFO Overflow Interrupt Mask */ +#define DW_SPI_IMR_TXEIM (0x01) /*!< Transmit FIFO Empty Interrupt Mask */ + +#define DW_SPI_IMR_XFER (DW_SPI_IMR_TXEIM|DW_SPI_IMR_RXFIM|DW_SPI_IMR_TXOIM|DW_SPI_IMR_RXOIM|DW_SPI_IMR_RXUIM) +/** @} */ + +#define DW_SPI_SSI_IDLE (1) +#define DW_SPI_SPI_TRANSMIT (1) +#define DW_SPI_SPI_RECEIVE (2) +#define DW_SPI_SSI_MASTER (1) +#define DW_SPI_SSI_SLAVE (0) + + +#endif /* _DEVICE_DW_SPI_HAL_H_ */ diff --git a/hw/mcu/arc/src/ext/sdk/device/designware/spi/dw_spi_hal_cfg.h b/hw/mcu/arc/src/ext/sdk/device/designware/spi/dw_spi_hal_cfg.h new file mode 100644 index 000000000..d6caf7146 --- /dev/null +++ b/hw/mcu/arc/src/ext/sdk/device/designware/spi/dw_spi_hal_cfg.h @@ -0,0 +1,58 @@ +/* ------------------------------------------ + * Copyright (c) 2017, Synopsys, Inc. All rights reserved. + + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + + * 1) Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + + * 2) 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. + + * 3) Neither the name of the Synopsys, Inc., nor the names of its contributors may + * be used to endorse or promote products derived from this software without + * specific prior written permission. + + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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. + * + * \version 2017.03 + * \date 2015-09-09 + * \author Huaqi Fang(Huaqi.Fang@synopsys.com) +--------------------------------------------- */ + +/** + * \file + * \ingroup DEVICE_DW_SPI + * \brief DesignWare SPI driver hardware description + * related header file configuration file + * \details configuration file to enable or disable some function of spi + */ + +#ifndef _DEVICE_DW_SPI_HAL_CFG_H_ +#define _DEVICE_DW_SPI_HAL_CFG_H_ + +#ifndef DW_SPI_CALC_FIFO_LEN_ENABLE +#define DW_SPI_CALC_FIFO_LEN_ENABLE (1) /*!< Defaultly enable calculate fifo length */ +#endif + +#ifndef DW_SPI_MAX_FIFO_LENGTH +#define DW_SPI_MAX_FIFO_LENGTH (256) /*!< Max FIFO depth for designware SPI device */ +#endif + +#ifndef DW_SPI_MIN_FIFO_LENGTH +#define DW_SPI_MIN_FIFO_LENGTH (2) /*!< Min FIFO depth for designware SPI device */ +#endif + +#endif /* _DEVICE_DW_SPI_HAL_CFG_H_ */ + diff --git a/hw/mcu/arc/src/ext/sdk/device/designware/uart/dw_uart.c b/hw/mcu/arc/src/ext/sdk/device/designware/uart/dw_uart.c new file mode 100644 index 000000000..999ee751e --- /dev/null +++ b/hw/mcu/arc/src/ext/sdk/device/designware/uart/dw_uart.c @@ -0,0 +1,956 @@ +/* ------------------------------------------ + * Copyright (c) 2016, Synopsys, Inc. All rights reserved. + + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + + * 1) Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + + * 2) 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. + + * 3) Neither the name of the Synopsys, Inc., nor the names of its contributors may + * be used to endorse or promote products derived from this software without + * specific prior written permission. + + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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. + * + * \version 2016.05 + * \date 2014-06-20 + * \author Huaqi Fang(Huaqi.Fang@synopsys.com) +--------------------------------------------- */ + +/** + * \defgroup DEVICE_DW_UART Designware UART Driver + * \ingroup DEVICE_DW + * \brief Designware UART Driver Implementation + */ + +/** + * \file + * \ingroup DEVICE_DW_UART + * \brief DesignWare UART driver implementation based on device hal layer definition (\ref dev_uart.h) + */ +#include + +#include "inc/embARC_toolchain.h" +#include "inc/embARC_error.h" + +#include "inc/arc/arc_exception.h" + +#include "device/designware/uart/dw_uart_hal.h" +#include "device/designware/uart/dw_uart.h" + + +/** + * \name DesignWare UART Driver Macros + * \brief DesignWare UART driver macros used in uart driver + * @{ + */ +/** check expressions used in DesignWare UART driver implementation */ +#define DW_UART_CHECK_EXP(EXPR, ERROR_CODE) CHECK_EXP(EXPR, ercd, ERROR_CODE, error_exit) + +#ifndef DISABLE_DEVICE_OBJECT_VALID_CHECK +/** valid check of uart info object */ +#define VALID_CHK_UART_INFO_OBJECT(uartinfo_obj_ptr) { \ + DW_UART_CHECK_EXP((uartinfo_obj_ptr)!=NULL, E_OBJ); \ + DW_UART_CHECK_EXP(((uartinfo_obj_ptr)->uart_ctrl)!=NULL, E_OBJ); \ + } +#endif + +/** convert DesignWare baudrate to divisor */ +#define DW_UART_BAUD2DIV(perifreq, baud) ((perifreq) / ((baud)*16)) + +/** + * \name DesignWare UART Interrupt Callback Routine Select Marcos + * \brief DesignWare UART interrupt callback routines select macros definitions + * @{ + */ +#define DW_UART_RDY_SND (1U) /*!< ready to send callback */ +#define DW_UART_RDY_RCV (2U) /*!< ready to receive callback */ +/** @} */ + +/** @} */ + +/** + * \defgroup DEVICE_DW_UART_STATIC DesignWare UART Driver Static Functions + * \ingroup DEVICE_DW_UART + * \brief Static or inline functions, variables for DesignWare UART handle uart operations, + * only used in this file + * @{ + */ +const uint8_t dw_uart_databits[] = { \ + DW_UART_LCR_WORD_LEN5, DW_UART_LCR_WORD_LEN6, \ + DW_UART_LCR_WORD_LEN7, DW_UART_LCR_WORD_LEN8}; +const uint8_t dw_uart_parity[] = { + DW_UART_LCR_PARITY_NONE, DW_UART_LCR_PARITY_ODD, + DW_UART_LCR_PARITY_EVEN, DW_UART_LCR_PARITY_MASK, + DW_UART_LCR_PARITY_SPACE +}; +const uint8_t dw_uart_stopbits[] = { + DW_UART_LCR_1_STOP_BIT, DW_UART_LCR_1D5_STOP_BIT, + DW_UART_LCR_2_STOP_BIT +}; + +/** test whether uart is ready to send, 1 ready, 0 not ready */ +Inline int32_t dw_uart_putready(DW_UART_REG *uart_reg_ptr) +{ + return ((uart_reg_ptr->USR & DW_UART_USR_TFNF) != 0); +} +/** test whether uart is ready to receive, 1 ready, 0 not ready */ +Inline int32_t dw_uart_getready(DW_UART_REG *uart_reg_ptr) +{ + return ((uart_reg_ptr->USR & DW_UART_USR_RFNE) != 0); +} +/** write char to uart send fifo */ +Inline void dw_uart_putchar(DW_UART_REG *uart_reg_ptr, char chr) +{ + uart_reg_ptr->DATA = chr; +} +/** read data from uart receive fifo, return data received */ +Inline int32_t dw_uart_getchar(DW_UART_REG *uart_reg_ptr) +{ + return (int32_t)uart_reg_ptr->DATA; +} +/** + * \brief send char by uart when available, + * mostly used in interrupt method, non-blocked function + * \param[in] uart_reg_ptr uart register structure pointer + * \param[in] chr char to be sent + * \retval 0 send successfully + * \retval -1 not ready to send data + */ +Inline int32_t dw_uart_snd_chr(DW_UART_REG *uart_reg_ptr, char chr) +{ + if (dw_uart_putready(uart_reg_ptr)) { + dw_uart_putchar(uart_reg_ptr, chr); + return 0; + } + return -1; +} +/** + * \brief receive one char from uart, + * mostly used in interrupt routine, non-blocked function + * \param[in] uart_reg_ptr uart register structure pointer + * \return data received by the uart + */ +Inline int32_t dw_uart_rcv_chr(DW_UART_REG *uart_reg_ptr) +{ + return dw_uart_getchar(uart_reg_ptr); +} +/** + * \brief send char by uart in poll method, blocked function + * \param[in] uart_reg_ptr uart register structure pointer + * \param[in] chr char to be sent + */ +Inline void dw_uart_psnd_chr(DW_UART_REG *uart_reg_ptr, char chr) +{ + /** wait until uart is ready to send */ + while (!dw_uart_putready(uart_reg_ptr)); /* blocked */ + /** send char */ + dw_uart_putchar(uart_reg_ptr, chr); +} +/** + * \brief receive one char from uart in poll method, blocked function + * \param[in] uart_reg_ptr uart register structure pointer + * \return data received by the uart + */ +Inline int32_t dw_uart_prcv_chr(DW_UART_REG *uart_reg_ptr) +{ + /** wait until uart is ready to receive */ + while (!dw_uart_getready(uart_reg_ptr)); /* blocked */ + /** receive data */ + return dw_uart_getchar(uart_reg_ptr); +} + +/** Get TX FIFO Length */ +Inline uint32_t dw_uart_get_txfifo_len(DW_UART_REG *uart_reg_ptr) +{ + uint32_t txfifolen; + uint32_t uart_cpr; + + uart_cpr = uart_reg_ptr->CPR; + if (uart_cpr & DW_UART_CPR_FIFO_STAT) { + txfifolen = ((uart_cpr & DW_UART_CPR_FIFO_MODE) >> DW_UART_CPR_FIFO_MODE_OFS) << 4; + } else { + txfifolen = 0; + } + + return txfifolen; +} + +/** Get RX FIFO Length */ +Inline uint32_t dw_uart_get_rxfifo_len(DW_UART_REG *uart_reg_ptr) +{ + uint32_t rxfifolen; + uint32_t uart_cpr; + + uart_cpr = uart_reg_ptr->CPR; + if (uart_cpr & DW_UART_CPR_FIFO_STAT) { + rxfifolen = ((uart_cpr & DW_UART_CPR_FIFO_MODE) >> DW_UART_CPR_FIFO_MODE_OFS) << 4; + } else { + rxfifolen = 0; + } + + return rxfifolen; +} + +/** + * \brief set designware uart DPS value + * \param uart_reg_ptr uart register structure + * \param dps data bits/parity bit/stop bits parameter + * \retval 0 Set ok + * \retval !0 Set failed + */ +static int32_t dw_uart_set_dps(DW_UART_REG *uart_reg_ptr, UART_DPS_FORMAT *dps) +{ + uint32_t dps_value = 0; + + if (dps == NULL) return -1; + /* data bits check */ + if ((dps->databits < 5) || (dps->databits > 8)) return -1; + /* stop bits check */ + if (dps->stopbits > UART_STPBITS_TWO) return -1; + /* parity bit type check */ + if (dps->parity > UART_PARITY_SPACE) return -1; + + dps_value |= (uint32_t)dw_uart_databits[dps->databits-5]; + dps_value |= (uint32_t)dw_uart_stopbits[dps->stopbits]; + dps_value |= (uint32_t)dw_uart_parity[dps->parity]; + + /* clear dps bits */ + uart_reg_ptr->LCR &= (~DW_UART_LCR_DPS_MASK); + /* set dps bits */ + uart_reg_ptr->LCR |= dps_value; + + return 0; +} + +/** + * \brief set designware uart baudrate + * \param uart_reg_ptr uart register structure + * \param baud_divisor uart baudrate divisor + */ +static void dw_uart_set_baud(DW_UART_REG *uart_reg_ptr, uint32_t baud_divisor) +{ + /* enable uart baudrate update */ + uart_reg_ptr->LCR |= DW_UART_LCR_DLAB; + /** + * setting uart baudrate registers + */ + uart_reg_ptr->DATA = baud_divisor & 0xff; /*!< DLL */ + uart_reg_ptr->IER = (baud_divisor>>8) & 0xff; /*!< DLH */ + /** disable DLAB */ + uart_reg_ptr->LCR &= ~(DW_UART_LCR_DLAB); +} + +/** + * \brief Do uart software reset + * \param uart_reg_ptr uart register structure + */ +Inline void dw_uart_software_reset(DW_UART_REG *uart_reg_ptr) +{ + uart_reg_ptr->SRR = DW_UART_SRR_UR|DW_UART_SRR_RFR|DW_UART_SRR_XFR; + while(uart_reg_ptr->USR & DW_UART_USR_BUSY); /* wait until software reset completed */ +} + +/** + * \brief set designware uart baudrate + * \param uart_reg_ptr uart register structure + * \param hwfc uart hardware flow control type + * \note Need to set corresponding pin functions + */ +static void dw_uart_set_hwfc(DW_UART_REG *uart_reg_ptr, UART_HW_FLOW_CONTROL hwfc) +{ + if (hwfc == UART_FC_NONE) { + uart_reg_ptr->MCR &= ~(DW_UART_MCR_AFCE|DW_UART_MCR_RTS); + } + if ((hwfc == UART_FC_RTS) || (hwfc == UART_FC_BOTH)) { + uart_reg_ptr->MCR |= (DW_UART_MCR_AFCE|DW_UART_MCR_RTS); + } + if ((hwfc == UART_FC_CTS) || (hwfc == UART_FC_BOTH)) { + uart_reg_ptr->MCR |= (DW_UART_MCR_AFCE); + } +} + +Inline void dw_uart_set_break(DW_UART_REG *uart_reg_ptr) +{ + uart_reg_ptr->LCR |= DW_UART_LCR_BREAK; +} + +Inline void dw_uart_clr_break(DW_UART_REG *uart_reg_ptr) +{ + uart_reg_ptr->LCR &= ~DW_UART_LCR_BREAK; +} + +/** + * \brief init designware uart with selected baud + * \param[in] uart_reg_ptr uart register structure pointer + * \param[in] baud_divisor baudrate divisor + */ +static void dw_uart_init(DW_UART_REG *uart_reg_ptr, uint32_t baud_divisor, UART_DPS_FORMAT *dps, UART_HW_FLOW_CONTROL hwfc) +{ + dw_uart_software_reset(uart_reg_ptr); + + dw_uart_set_hwfc(uart_reg_ptr, hwfc); + dw_uart_set_dps(uart_reg_ptr, dps); + dw_uart_set_baud(uart_reg_ptr, baud_divisor); + + uart_reg_ptr->IIR = 0x1; /** enable uart fifo (FCR IIR is the same) */ + uart_reg_ptr->IER = 0x0; /** disable all uart interrupt */ +} + +/** + * \brief set designware uart baudrate + * \param uart_info_ptr uart information structure pointer + */ +static void dw_uart_flush_output(DEV_UART_INFO *uart_info_ptr) +{ + uint32_t i; + char *p_charbuf; + + DW_UART_CTRL *uart_ctrl_ptr = (DW_UART_CTRL_PTR)(uart_info_ptr->uart_ctrl); + DW_UART_REG *uart_reg_ptr = (DW_UART_REG_PTR)(uart_ctrl_ptr->dw_uart_regbase); + + if (uart_info_ptr->tx_buf.buf != NULL) { + p_charbuf = (char *)(uart_info_ptr->tx_buf.buf); + for (i = uart_info_ptr->tx_buf.ofs; i < uart_info_ptr->tx_buf.len; i ++) { + dw_uart_psnd_chr(uart_reg_ptr, p_charbuf[i]); + } + /* clear transmit buffer */ + uart_info_ptr->tx_buf.buf = NULL; + uart_info_ptr->tx_buf.len = 0; + uart_info_ptr->tx_buf.ofs = 0; + } + /* wait until transmit fifo is empty */ + while ((uart_reg_ptr->USR & DW_UART_USR_TFE) == 0); + while (uart_reg_ptr->USR & DW_UART_USR_BUSY); +} + +/** + * \brief disable designware uart send or receive interrupt + * \param[in] DEV_UART_INFO *uart_info_ptr + * \param[in] cbrtn control code of callback routine of send or receive + */ +static void dw_uart_dis_cbr(DEV_UART_INFO *uart_info_ptr, uint32_t cbrtn) +{ + DW_UART_CTRL *uart_ctrl_ptr = (DW_UART_CTRL_PTR)(uart_info_ptr->uart_ctrl); + DW_UART_REG *uart_reg_ptr = (DW_UART_REG_PTR)(uart_ctrl_ptr->dw_uart_regbase); + + switch (cbrtn) { + case DW_UART_RDY_SND: + uart_reg_ptr->IER &= ~DW_UART_IER_XMIT_EMPTY; + uart_ctrl_ptr->int_status &= ~DW_UART_TXINT_ENABLE; + break; + case DW_UART_RDY_RCV: + uart_reg_ptr->IER &= ~DW_UART_IER_DATA_AVAIL; + uart_ctrl_ptr->int_status &= ~DW_UART_RXINT_ENABLE; + break; + default: + break; + } + if (uart_ctrl_ptr->int_status & DW_UART_GINT_ENABLE) { + if ((uart_ctrl_ptr->int_status & (DW_UART_RXINT_ENABLE|DW_UART_TXINT_ENABLE)) == 0) { + int_disable(uart_ctrl_ptr->intno); + uart_ctrl_ptr->int_status &= ~DW_UART_GINT_ENABLE; + } + } +} + +/** + * \brief enable DesignWare UART send or receive interrupt + * \param[in] DEV_UART_INFO *uart_info_ptr + * \param[in] cbrtn control code of callback routine of send or receive + */ +static void dw_uart_ena_cbr(DEV_UART_INFO *uart_info_ptr, uint32_t cbrtn) +{ + DW_UART_CTRL *uart_ctrl_ptr = (DW_UART_CTRL_PTR)(uart_info_ptr->uart_ctrl); + DW_UART_REG *uart_reg_ptr = (DW_UART_REG_PTR)(uart_ctrl_ptr->dw_uart_regbase); + + switch (cbrtn) { + case DW_UART_RDY_SND: + uart_ctrl_ptr->int_status |= DW_UART_TXINT_ENABLE; + uart_reg_ptr->IER |= DW_UART_IER_XMIT_EMPTY; + break; + case DW_UART_RDY_RCV: + uart_ctrl_ptr->int_status |= DW_UART_RXINT_ENABLE; + uart_reg_ptr->IER |= DW_UART_IER_DATA_AVAIL; + break; + default: + break; + } + if ((uart_ctrl_ptr->int_status & DW_UART_GINT_ENABLE) == 0) { + if (uart_ctrl_ptr->int_status & (DW_UART_RXINT_ENABLE|DW_UART_TXINT_ENABLE)) { + uart_ctrl_ptr->int_status |= DW_UART_GINT_ENABLE; + int_enable(uart_ctrl_ptr->intno); + } + } +} + +/** + * \brief enable designware uart interrupt + * \param uart_info_ptr uart information structure pointer + */ +static void dw_uart_enable_interrupt(DEV_UART_INFO *uart_info_ptr) +{ + DW_UART_CTRL *uart_ctrl_ptr = (DW_UART_CTRL_PTR)(uart_info_ptr->uart_ctrl); + + int_handler_install(uart_ctrl_ptr->intno, uart_ctrl_ptr->dw_uart_int_handler); + uart_ctrl_ptr->int_status |= DW_UART_GINT_ENABLE; + int_enable(uart_ctrl_ptr->intno); /** enable uart interrupt */ +} +/** + * \brief disable designware uart interrupt + * \param uart_info_ptr uart information structure pointer + */ +static void dw_uart_disable_interrupt(DEV_UART_INFO *uart_info_ptr) +{ + DW_UART_CTRL *uart_ctrl_ptr = (DW_UART_CTRL_PTR)(uart_info_ptr->uart_ctrl); + + /** disable uart send&receive interrupt after disable uart interrupt */ + dw_uart_dis_cbr(uart_info_ptr, DW_UART_RDY_SND); + dw_uart_dis_cbr(uart_info_ptr, DW_UART_RDY_RCV); + /* disable uart interrupt */ + int_disable(uart_ctrl_ptr->intno); + uart_ctrl_ptr->int_status &= ~(DW_UART_GINT_ENABLE|DW_UART_TXINT_ENABLE|DW_UART_RXINT_ENABLE); +} + +/** enable designware uart */ +static void dw_uart_enable_device(DEV_UART_INFO *uart_info_ptr) +{ + DW_UART_CTRL *uart_ctrl_ptr = (DW_UART_CTRL_PTR)(uart_info_ptr->uart_ctrl); + DW_UART_REG *uart_reg_ptr = (DW_UART_REG_PTR)(uart_ctrl_ptr->dw_uart_regbase); + + if ((uart_info_ptr->status & DEV_ENABLED) == 0) { + dw_uart_set_baud(uart_reg_ptr, uart_info_ptr->baudrate); + uart_info_ptr->status |= DEV_ENABLED; + } +} + +/** disable designware uart */ +static void dw_uart_disable_device(DEV_UART_INFO *uart_info_ptr) +{ + DW_UART_CTRL *uart_ctrl_ptr = (DW_UART_CTRL_PTR)(uart_info_ptr->uart_ctrl); + DW_UART_REG *uart_reg_ptr = (DW_UART_REG_PTR)(uart_ctrl_ptr->dw_uart_regbase); + + if ((uart_info_ptr->status & DEV_ENABLED) == DEV_ENABLED) { + dw_uart_set_baud(uart_reg_ptr, 0); + uart_info_ptr->status &= ~DEV_ENABLED; + } +} + +/** abort current interrupt transmit transfer */ +static void dw_uart_abort_tx(DEV_UART *uart_obj) +{ + DEV_UART_INFO *uart_info_ptr = &(uart_obj->uart_info); + DW_UART_CTRL *uart_ctrl_ptr = (DW_UART_CTRL_PTR)(uart_info_ptr->uart_ctrl); + + if (uart_ctrl_ptr->int_status & DW_UART_TXINT_ENABLE) { + dw_uart_dis_cbr(uart_info_ptr, DW_UART_RDY_SND); + uart_info_ptr->status |= DEV_IN_TX_ABRT; + if (uart_info_ptr->uart_cbs.tx_cb != NULL) { + uart_info_ptr->uart_cbs.tx_cb(uart_obj); + } + uart_info_ptr->status &= ~(DEV_IN_TX_ABRT); + } +} + +/** abort current interrupt receive transfer */ +static void dw_uart_abort_rx(DEV_UART *uart_obj) +{ + DEV_UART_INFO *uart_info_ptr = &(uart_obj->uart_info); + DW_UART_CTRL *uart_ctrl_ptr = (DW_UART_CTRL_PTR)(uart_info_ptr->uart_ctrl); + + if (uart_ctrl_ptr->int_status & DW_UART_RXINT_ENABLE) { + dw_uart_dis_cbr(uart_info_ptr, DW_UART_RDY_RCV); + uart_info_ptr->status |= DEV_IN_RX_ABRT; + if (uart_info_ptr->uart_cbs.rx_cb != NULL) { + uart_info_ptr->uart_cbs.rx_cb(uart_obj); + } + uart_info_ptr->status &= ~(DEV_IN_RX_ABRT); + } +} + +/** Get available transmit fifo count */ +static int32_t dw_uart_get_txavail(DW_UART_CTRL *uart_ctrl_ptr) +{ + int32_t tx_avail = 0; + DW_UART_REG *uart_reg_ptr = (DW_UART_REG *)(uart_ctrl_ptr->dw_uart_regbase); + + if (uart_ctrl_ptr->tx_fifo_len <= 1) { + if (dw_uart_putready(uart_reg_ptr) == 1) { + tx_avail = 1; + } else { + tx_avail = 0; + } + } else { + tx_avail = uart_ctrl_ptr->tx_fifo_len - uart_reg_ptr->TFL; + } + return tx_avail; +} + +/** Get available receive fifo count */ +static int32_t dw_uart_get_rxavail(DW_UART_CTRL *uart_ctrl_ptr) +{ + int32_t rx_avail = 0; + DW_UART_REG *uart_reg_ptr = (DW_UART_REG *)(uart_ctrl_ptr->dw_uart_regbase); + + if (uart_ctrl_ptr->rx_fifo_len <= 1) { + if (dw_uart_getready(uart_reg_ptr) == 1) { + rx_avail = 1; + } else { + rx_avail = 0; + } + } else { + rx_avail = uart_reg_ptr->RFL; + } + return rx_avail; +} + + +/** @} end of group DEVICE_DW_UART_STATIC */ + +/** + * \brief open a designware uart device + * \param[in] uart_obj uart object structure pointer + * \param[in] baud baudrate to initialized + * \retval E_OK Open successfully without any issues + * \retval E_OPNED If device was opened before with different baudrate, then return E_OPNED + * \retval E_OBJ Device object is not valid + * \retval E_PAR Parameter is not valid + * \retval E_NOSPT Open settings are not supported + */ +int32_t dw_uart_open (DEV_UART *uart_obj, uint32_t baud) +{ + int32_t ercd = E_OK; + DEV_UART_INFO *uart_info_ptr = &(uart_obj->uart_info); + + /* START ERROR CHECK */ + VALID_CHK_UART_INFO_OBJECT(uart_info_ptr); + DW_UART_CHECK_EXP(baud>0, E_PAR); + /* END OF ERROR CHECK */ + + uart_info_ptr->opn_cnt ++; + if (uart_info_ptr->opn_cnt > 1) { /* opened before */ + if (baud == uart_info_ptr->baudrate) { /* baudrate is the same */ + return E_OK; + } else { /* open with different baudrate */ + return E_OPNED; + } + } + + int32_t baud_divisor = 0; + + DW_UART_CTRL *uart_ctrl_ptr = (DW_UART_CTRL_PTR)(uart_info_ptr->uart_ctrl); + DW_UART_REG *uart_reg_ptr = (DW_UART_REG_PTR)(uart_ctrl_ptr->dw_uart_regbase); + + /* Get FIFO Length */ + uart_ctrl_ptr->tx_fifo_len = dw_uart_get_txfifo_len(uart_reg_ptr); + uart_ctrl_ptr->rx_fifo_len = dw_uart_get_rxfifo_len(uart_reg_ptr); + + /** init uart */ + uart_info_ptr->baudrate = baud; + baud_divisor = DW_UART_BAUD2DIV(uart_ctrl_ptr->dw_apb_bus_freq, baud); + uart_info_ptr->dps_format = dps_format_default; + uart_info_ptr->hwfc = hwfc_default; + dw_uart_init(uart_reg_ptr, baud_divisor, &(uart_info_ptr->dps_format), uart_info_ptr->hwfc); + + uart_info_ptr->status = DEV_ENABLED; + uart_info_ptr->extra = NULL; + + /** + * uart interrupt related init + */ + dw_uart_disable_interrupt(uart_info_ptr); + /** install uart interrupt into system */ + int_handler_install(uart_ctrl_ptr->intno, uart_ctrl_ptr->dw_uart_int_handler); + + memset(&(uart_info_ptr->tx_buf), 0, sizeof(DEV_BUFFER)); + memset(&(uart_info_ptr->rx_buf), 0, sizeof(DEV_BUFFER)); + memset(&(uart_info_ptr->uart_cbs), 0, sizeof(DEV_UART_CBS)); + +error_exit: + return ercd; +} + +/** + * \brief close a DesignWare UART device + * \param[in] uart_obj uart object structure pointer + * \retval E_OK Open successfully without any issues + * \retval E_OPNED Device is still opened, the device opn_cnt decreased by 1 + * \retval E_OBJ Device object is not valid + */ +int32_t dw_uart_close (DEV_UART *uart_obj) +{ + int32_t ercd = E_OK; + DEV_UART_INFO *uart_info_ptr = &(uart_obj->uart_info); + + /* START ERROR CHECK */ + VALID_CHK_UART_INFO_OBJECT(uart_info_ptr); + DW_UART_CHECK_EXP(uart_info_ptr->opn_cnt > 0, E_OK); + /* END OF ERROR CHECK */ + + uart_info_ptr->opn_cnt --; + if (uart_info_ptr->opn_cnt == 0) { + dw_uart_disable_interrupt(uart_info_ptr); + dw_uart_abort_tx(uart_obj); + dw_uart_abort_rx(uart_obj); + dw_uart_flush_output(uart_info_ptr); + memset(&(uart_info_ptr->tx_buf), 0, sizeof(DEV_BUFFER)); + memset(&(uart_info_ptr->rx_buf), 0, sizeof(DEV_BUFFER)); + memset(&(uart_info_ptr->uart_cbs), 0, sizeof(DEV_UART_CBS)); + dw_uart_disable_device(uart_info_ptr); + uart_info_ptr->status = 0; + uart_info_ptr->extra = NULL; + } else { + ercd = E_OPNED; + } + +error_exit: + return ercd; +} + +/** + * \brief control uart by ctrl command + * \param[in] uart_obj uart object structure pointer + * \param[in] ctrl_cmd control command code to do specific uart work + * \param[in,out] param parameters used to control uart or return something + * \retval E_OK Control device successfully + * \retval E_CLSED Device is not opened + * \retval E_DIS Device is disabled + * \retval E_OBJ Device object is not valid or not exists + * \retval E_PAR Parameter is not valid for current control command + * \retval E_SYS Control device failed, due to hardware issues + * \retval E_CTX Control device failed, due to different reasons like in transfer state + * \retval E_NOSPT Control command is not supported or not valid + */ +int32_t dw_uart_control (DEV_UART *uart_obj, uint32_t ctrl_cmd, void *param) +{ + int32_t ercd = E_OK; + DEV_UART_INFO *uart_info_ptr = &(uart_obj->uart_info); + + /* START ERROR CHECK */ + VALID_CHK_UART_INFO_OBJECT(uart_info_ptr); + DW_UART_CHECK_EXP(uart_info_ptr->opn_cnt > 0, E_CLSED); + /* END OF ERROR CHECK */ + + uint32_t val32; /** to receive unsigned int value */ + int32_t baud_divisor = 0; + DEV_BUFFER *devbuf; + UART_DPS_FORMAT *dps_ptr; + UART_HW_FLOW_CONTROL hwfc_local; + + DW_UART_CTRL *uart_ctrl_ptr = (DW_UART_CTRL_PTR)(uart_info_ptr->uart_ctrl); + DW_UART_REG *uart_reg_ptr = (DW_UART_REG_PTR)(uart_ctrl_ptr->dw_uart_regbase); + + /* check whether current device is disabled */ + if ((uart_info_ptr->status & DEV_ENABLED) == 0) { + /** When device is disabled, + * only UART_CMD_ENA_DEV, UART_CMD_DIS_DEV, UART_CMD_GET_STATUS + * are available, other commands will return E_SYS + */ + if ((ctrl_cmd != UART_CMD_ENA_DEV) && \ + (ctrl_cmd != UART_CMD_DIS_DEV) && \ + (ctrl_cmd != UART_CMD_GET_STATUS) ) { + return E_SYS; + } + } + + switch (ctrl_cmd) { + case UART_CMD_SET_BAUD: + val32 = (uint32_t)param; + DW_UART_CHECK_EXP(val32>0, E_PAR); + if (val32 != uart_info_ptr->baudrate) { + baud_divisor = DW_UART_BAUD2DIV(uart_ctrl_ptr->dw_apb_bus_freq, val32); + dw_uart_set_baud(uart_reg_ptr, baud_divisor); + uart_info_ptr->baudrate = val32; + } + break; + case UART_CMD_GET_STATUS: + DW_UART_CHECK_EXP((param!=NULL) && CHECK_ALIGN_4BYTES(param), E_PAR); + *((int32_t *)param) = uart_info_ptr->status; + break; + case UART_CMD_ENA_DEV: + dw_uart_enable_device(uart_info_ptr); + break; + case UART_CMD_DIS_DEV: + dw_uart_disable_device(uart_info_ptr); + break; + case UART_CMD_FLUSH_OUTPUT: + dw_uart_flush_output(uart_info_ptr); + break; + case UART_CMD_GET_RXAVAIL: + DW_UART_CHECK_EXP((param!=NULL) && CHECK_ALIGN_4BYTES(param), E_PAR); + *((int32_t *)param) = dw_uart_get_rxavail(uart_ctrl_ptr); + break; + case UART_CMD_GET_TXAVAIL: + DW_UART_CHECK_EXP((param!=NULL) && CHECK_ALIGN_4BYTES(param), E_PAR); + *((int32_t *)param) = dw_uart_get_txavail(uart_ctrl_ptr); + break; + case UART_CMD_BREAK_SET: + dw_uart_set_break(uart_reg_ptr); + break; + case UART_CMD_BREAK_CLR: + dw_uart_clr_break(uart_reg_ptr); + break; + case UART_CMD_SET_DPS_FORMAT: + DW_UART_CHECK_EXP(param!=NULL, E_PAR); + dps_ptr = (UART_DPS_FORMAT *)param; + if (dw_uart_set_dps(uart_reg_ptr, dps_ptr) == 0) { + uart_info_ptr->dps_format = *dps_ptr; + } else { + ercd = E_PAR; + } + break; + case UART_CMD_SET_HWFC: + hwfc_local = (UART_HW_FLOW_CONTROL)param; + DW_UART_CHECK_EXP(((hwfc_local>=UART_FC_NONE) && (hwfc_local<=UART_FC_BOTH)), E_PAR); + dw_uart_set_hwfc(uart_reg_ptr, hwfc_local); + uart_info_ptr->hwfc = hwfc_local; + break; + case UART_CMD_SET_TXCB: + DW_UART_CHECK_EXP(CHECK_ALIGN_4BYTES(param), E_PAR); + uart_info_ptr->uart_cbs.tx_cb = param; + break; + case UART_CMD_SET_RXCB: + DW_UART_CHECK_EXP(CHECK_ALIGN_4BYTES(param), E_PAR); + uart_info_ptr->uart_cbs.rx_cb = param; + break; + case UART_CMD_SET_ERRCB: + DW_UART_CHECK_EXP(CHECK_ALIGN_4BYTES(param), E_PAR); + uart_info_ptr->uart_cbs.err_cb = param; + break; + case UART_CMD_ABORT_TX: + dw_uart_abort_tx(uart_obj); + break; + case UART_CMD_ABORT_RX: + dw_uart_abort_rx(uart_obj); + break; + case UART_CMD_SET_TXINT: + val32 = (uint32_t)param; + if (val32 == 0) { + dw_uart_dis_cbr(uart_info_ptr, DW_UART_RDY_SND); + } else { + dw_uart_ena_cbr(uart_info_ptr, DW_UART_RDY_SND); + } + break; + case UART_CMD_SET_RXINT: + val32 = (uint32_t)param; + if (val32 == 0) { + dw_uart_dis_cbr(uart_info_ptr, DW_UART_RDY_RCV); + } else { + dw_uart_ena_cbr(uart_info_ptr, DW_UART_RDY_RCV); + } + break; + case UART_CMD_SET_TXINT_BUF: + DW_UART_CHECK_EXP(CHECK_ALIGN_4BYTES(param), E_PAR); + if (param != NULL) { + devbuf = (DEV_BUFFER *)param; + uart_info_ptr->tx_buf = *devbuf; + uart_info_ptr->tx_buf.ofs = 0; + } else { + uart_info_ptr->tx_buf.buf = NULL; + uart_info_ptr->tx_buf.len = 0; + uart_info_ptr->tx_buf.ofs = 0; + } + break; + case UART_CMD_SET_RXINT_BUF: + DW_UART_CHECK_EXP(CHECK_ALIGN_4BYTES(param), E_PAR); + if (param != NULL) { + devbuf = (DEV_BUFFER *)param; + uart_info_ptr->rx_buf = *devbuf; + uart_info_ptr->rx_buf.ofs = 0; + } else { + uart_info_ptr->rx_buf.buf = NULL; + uart_info_ptr->rx_buf.len = 0; + uart_info_ptr->rx_buf.ofs = 0; + } + break; + default: + ercd = E_NOSPT; + break; + } + +error_exit: + return ercd; +} + +/** + * \brief send data through DesignWare UART + * \param[in] uart_obj uart object structure pointer + * \param[in] data data that need to send (data must be char type) + * \param[in] len data length need to send + * \retval >0 Byte count that was successfully sent for poll method + * \retval E_OBJ Device object is not valid or not exists + * \retval E_PAR Parameter is not valid for current control command + * \retval E_SYS Can't write data to hardware due to hardware issues + */ +int32_t dw_uart_write (DEV_UART *uart_obj, const void *data, uint32_t len) +{ + int32_t ercd = E_OK; + DEV_UART_INFO *uart_info_ptr = &(uart_obj->uart_info); + + /* START ERROR CHECK */ + VALID_CHK_UART_INFO_OBJECT(uart_info_ptr); + DW_UART_CHECK_EXP(uart_info_ptr->opn_cnt > 0, E_CLSED); + DW_UART_CHECK_EXP(uart_info_ptr->status & DEV_ENABLED, E_SYS); + DW_UART_CHECK_EXP(data!=NULL, E_PAR); + DW_UART_CHECK_EXP(len>0, E_PAR); + /* END OF ERROR CHECK */ + + int32_t i = 0; + const char *p_charbuf = (const char *)data; + + DW_UART_CTRL *uart_ctrl_ptr = (DW_UART_CTRL_PTR)(uart_info_ptr->uart_ctrl); + DW_UART_REG *uart_reg_ptr = (DW_UART_REG_PTR)(uart_ctrl_ptr->dw_uart_regbase); + + while (i < len) { + dw_uart_psnd_chr(uart_reg_ptr, p_charbuf[i++]); + } + ercd = i; + +error_exit: + return ercd; +} + +/** + * \brief read data through DesignWare UART + * \param[in] uart_obj uart object structure pointer + * \param[out] data data that need to read (data must be char type) + * \param[in] len data count need to read + * \retval >0 Byte count that was successfully sent for poll method + * \retval E_OBJ Device object is not valid or not exists + * \retval E_PAR Parameter is not valid for current control command + * \retval E_SYS Can't receive data from hardware due to hardware issues, such as device is disabled + */ +int32_t dw_uart_read (DEV_UART *uart_obj, void *data, uint32_t len) +{ + int32_t ercd = E_OK; + DEV_UART_INFO *uart_info_ptr = &(uart_obj->uart_info); + + /* START ERROR CHECK */ + VALID_CHK_UART_INFO_OBJECT(uart_info_ptr); + DW_UART_CHECK_EXP(uart_info_ptr->opn_cnt > 0, E_CLSED); + DW_UART_CHECK_EXP(uart_info_ptr->status & DEV_ENABLED, E_SYS); + DW_UART_CHECK_EXP(data!=NULL, E_PAR); + DW_UART_CHECK_EXP(len>0, E_PAR); + /* END OF ERROR CHECK */ + + int32_t i = 0; + char *p_charbuf = (char *)data; + + DW_UART_CTRL *uart_ctrl_ptr = (DW_UART_CTRL_PTR)(uart_info_ptr->uart_ctrl); + DW_UART_REG *uart_reg_ptr = (DW_UART_REG_PTR)(uart_ctrl_ptr->dw_uart_regbase); + + while (i < len) { + p_charbuf[i++] = dw_uart_prcv_chr(uart_reg_ptr); + } + ercd = i; + +error_exit: + return ercd; +} + +/** + * \brief DesignWare UART interrupt processing routine + * \param[in] uart_obj uart object structure pointer + * \param[in] ptr extra information + */ +void dw_uart_isr (DEV_UART *uart_obj, void *ptr) +{ + int32_t ercd = E_OK; + DEV_UART_INFO *uart_info_ptr = &(uart_obj->uart_info); + + /* START ERROR CHECK */ + VALID_CHK_UART_INFO_OBJECT(uart_info_ptr); + /* END OF ERROR CHECK */ + + uint32_t uart_int_status; /** uart interrupt status */ + volatile uint32_t temp; /** read error status to clear interrupt */ + DEV_BUFFER *buf_ptr; + char *p_charbuf; + + DW_UART_CTRL *uart_ctrl_ptr = (DW_UART_CTRL_PTR)(uart_info_ptr->uart_ctrl); + DW_UART_REG *uart_reg_ptr = (DW_UART_REG_PTR)(uart_ctrl_ptr->dw_uart_regbase); + + /** get uart interrupt status */ + uart_int_status = (uart_reg_ptr->IIR) & DW_UART_IIR_INT_ID_MASK; + + switch (uart_int_status) { + case DW_UART_IIR_MDM_STATUS: + temp = (volatile uint32_t)(uart_reg_ptr->MSR); + break; + case DW_UART_IIR_LINE_STATUS: + if (uart_info_ptr->uart_cbs.err_cb) { + uart_info_ptr->uart_cbs.err_cb(uart_info_ptr); + } + temp = (volatile uint32_t)(uart_reg_ptr->LSR); + break; + case DW_UART_IIR_XMIT_EMPTY: + buf_ptr = &(uart_info_ptr->tx_buf); + p_charbuf = (char *)buf_ptr->buf; + if (p_charbuf != NULL) { + while (dw_uart_putready(uart_reg_ptr)) { + dw_uart_putchar(uart_reg_ptr, p_charbuf[buf_ptr->ofs]); + buf_ptr->ofs ++; + if (buf_ptr->ofs >= buf_ptr->len) { + dw_uart_dis_cbr(uart_info_ptr, DW_UART_RDY_SND); + if (uart_info_ptr->uart_cbs.tx_cb) { + uart_info_ptr->uart_cbs.tx_cb(uart_obj); + } + /* clear the send buffer pointer */ + memset(buf_ptr, 0, sizeof(DEV_BUFFER)); + break; + } + } + } else { + if (uart_info_ptr->uart_cbs.tx_cb) { + uart_info_ptr->uart_cbs.tx_cb(uart_obj); + } + } + break; + case DW_UART_IIR_RX_TIMEOUT: + temp = dw_uart_getchar(uart_reg_ptr); + break; + case DW_UART_IIR_DATA_AVAIL: + buf_ptr = &(uart_info_ptr->rx_buf); + p_charbuf = (char *)buf_ptr->buf; + if (p_charbuf != NULL) { + while (dw_uart_getready(uart_reg_ptr)) { + p_charbuf[buf_ptr->ofs] = (char)dw_uart_getchar(uart_reg_ptr); + buf_ptr->ofs ++; + if (buf_ptr->ofs >= buf_ptr->len) { + dw_uart_dis_cbr(uart_info_ptr, DW_UART_RDY_RCV); + if (uart_info_ptr->uart_cbs.rx_cb) { + uart_info_ptr->uart_cbs.rx_cb(uart_obj); + } + /* clear the send buffer pointer */ + memset(buf_ptr, 0, sizeof(DEV_BUFFER)); + break; + } + } + } else { + if (uart_info_ptr->uart_cbs.rx_cb) { + uart_info_ptr->uart_cbs.rx_cb(uart_obj); + } + } + break; + default: + temp = (volatile uint32_t)(uart_reg_ptr->USR); + break; + } + +error_exit: + return; +} diff --git a/hw/mcu/arc/src/ext/sdk/device/designware/uart/dw_uart.h b/hw/mcu/arc/src/ext/sdk/device/designware/uart/dw_uart.h new file mode 100644 index 000000000..366c4fccc --- /dev/null +++ b/hw/mcu/arc/src/ext/sdk/device/designware/uart/dw_uart.h @@ -0,0 +1,141 @@ +/* ------------------------------------------ + * Copyright (c) 2016, Synopsys, Inc. All rights reserved. + + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + + * 1) Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + + * 2) 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. + + * 3) Neither the name of the Synopsys, Inc., nor the names of its contributors may + * be used to endorse or promote products derived from this software without + * specific prior written permission. + + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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. + * + * \version 2016.05 + * \date 2014-06-20 + * \author Huaqi Fang(Huaqi.Fang@synopsys.com) +--------------------------------------------- */ + +/** + * \file + * \ingroup DEVICE_DW_UART + * \brief DesignWare UART driver header file + * \details detailed definitions of designware uart driver + */ + +#ifndef _DW_UART_H_ +#define _DW_UART_H_ + +#include "device/device_hal/inc/dev_uart.h" + +#include "inc/arc/arc_exception.h" + +/** + * if this header file is included, + * will indicate that this designware uart device + * is used + */ +#define DEVICE_USE_DESIGNWARE_UART + +/** + * \name DesignWare UART Register Structure + * \brief contains definitions of DesignWare UART register structure. + * @{ + */ +/** + * \brief DesignWare UART register structure + * \details Detailed struct description of DesignWare UART + * block register information, implementation of dev_uart_info::uart_regs + */ +typedef volatile struct dw_uart_reg { + uint32_t DATA; /*!< data in/out and DLL */ + uint32_t IER; /*!< Interrupt enable register and DLH */ + uint32_t IIR; /*!< Interrupt Id register and FCR */ + uint32_t LCR; /*!< Line control Register */ + uint32_t MCR; /*!< Modem control register */ + uint32_t LSR; /*!< Line Status Register */ + uint32_t MSR; /*!< Modem status Register */ + uint32_t SCRATCHPAD; /*!< Uart scratch pad register */ + uint32_t LPDLL; /*!< Low Power Divisor Latch (Low) Reg */ + uint32_t LPDLH; /*!< Low Power Divisor Latch (High) Reg */ + uint32_t RES1[2]; /*!< Reserved */ + uint32_t SHR[16]; /*!< Shadow data register(SRBR and STHR) */ + uint32_t FAR; /*!< FIFO Access register */ + uint32_t TFR; /*!< Transmit FIFO Read */ + uint32_t RFW; /*!< Receive FIFO write */ + uint32_t USR; /*!< UART status register */ + uint32_t TFL; /*!< Transmit FIFO level */ + uint32_t RFL; /*!< Receive FIFO level */ + uint32_t SRR; /*!< Software reset register */ + uint32_t SRTS; /*!< Shadow request to send */ + uint32_t SBCR; /*!< Shadow break control */ + uint32_t SDMAM; /*!< Shadow DMA mode */ + uint32_t SFE; /*!< Shadow FIFO enable */ + uint32_t SRT; /*!< Shadow RCVR Trigger */ + uint32_t STET; /*!< Shadow TX empty register */ + uint32_t HTX; /*!< Halt TX */ + uint32_t DMASA; /*!< DMA Software ACK */ + uint32_t RES2[18]; /*!< Reserved */ + uint32_t CPR; /*!< Camponent parameter register */ + uint32_t UCV; /*!< UART Component Version */ + uint32_t CTR; /*!< Component typw register */ +} DW_UART_REG, *DW_UART_REG_PTR; +/** @} */ + +#define DW_UART_GINT_DISABLED (0) /*!< designware interrupt disabled for control uart irq/fiq */ +#define DW_UART_GINT_ENABLE (1<<0) /*!< designware interrupt enabled for control uart irq/fiq */ +#define DW_UART_TXINT_ENABLE (1<<1) /*!< designware interrupt enabled for control transmit process */ +#define DW_UART_RXINT_ENABLE (1<<2) /*!< designware interrupt enabled for control transmit process */ + +/** + * \brief DesignWare UART control structure definition + * \details implement of dev_uart_info::uart_ctrl + */ +typedef struct dw_uart_ctrl { + uint32_t dw_uart_regbase; /*!< uart ip register base */ + uint32_t dw_apb_bus_freq; /*!< uart ip apb bus frequency */ + uint32_t intno; /*!< uart interrupt vector number */ + INT_HANDLER dw_uart_int_handler; /*!< uart interrupt handler */ + uint32_t tx_fifo_len; /*!< transmit fifo length, set by user in object implementation */ + uint32_t rx_fifo_len; /*!< receive fifo length, set by user in object implementation */ + uint32_t int_status; /*!< interrupt status for designware uart */ +} DW_UART_CTRL, *DW_UART_CTRL_PTR; + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \name DesignWare UART Function Declaration + * \brief contains declarations of designware uart functions. + * \details This are only used in uart object implementation source file + * @{ + */ +extern int32_t dw_uart_open (DEV_UART *uart_obj, uint32_t baud); +extern int32_t dw_uart_close (DEV_UART *uart_obj); +extern int32_t dw_uart_control (DEV_UART *uart_obj, uint32_t ctrl_cmd, void *param); +extern int32_t dw_uart_write (DEV_UART *uart_obj, const void *data, uint32_t len); +extern int32_t dw_uart_read (DEV_UART *uart_obj, void *data, uint32_t len); +extern void dw_uart_isr(DEV_UART *uart_obj, void *ptr); +/** @} */ + +#ifdef __cplusplus +} +#endif + +#endif /* _DW_UART_H_ */ diff --git a/hw/mcu/arc/src/ext/sdk/device/designware/uart/dw_uart_hal.h b/hw/mcu/arc/src/ext/sdk/device/designware/uart/dw_uart_hal.h new file mode 100644 index 000000000..367894df9 --- /dev/null +++ b/hw/mcu/arc/src/ext/sdk/device/designware/uart/dw_uart_hal.h @@ -0,0 +1,253 @@ +/* ------------------------------------------ + * Copyright (c) 2016, Synopsys, Inc. All rights reserved. + + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + + * 1) Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + + * 2) 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. + + * 3) Neither the name of the Synopsys, Inc., nor the names of its contributors may + * be used to endorse or promote products derived from this software without + * specific prior written permission. + + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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. + * + * \version 2016.05 + * \date 2014-06-20 + * \author Huaqi Fang(Huaqi.Fang@synopsys.com) +--------------------------------------------- */ + +/** + * \file + * \ingroup DEVICE_DW_IIC + * \brief DesignWare UART driver hardware description related header file + * \details detailed hardware related definitions of DesignWare UART driver + */ + +#ifndef _DEVICE_DW_UART_HAL_H_ +#define _DEVICE_DW_UART_HAL_H_ + +/* DW APB UART bit definitions */ + +/** + * \name DesignWare UART HAL IER Marcos + * \brief DesignWare UART hal IER related macros + * @{ + */ +/* IER */ +#define DW_UART_IER_DATA_AVAIL (0x01) +#define DW_UART_IER_XMIT_EMPTY (0x02) +#define DW_UART_IER_LINE_STATUS (0x04) +#define DW_UART_IER_MDM_STATUS (0x08) +#define DW_UART_IER_PTIME (0x80) +/** @} */ + +/** + * \name DesignWare UART HAL IIR Marcos + * \brief DesignWare UART hal IIR related macros + * @{ + */ +/* IIR */ +/* IIR READ */ +#define DW_UART_IIR_IP (0x01) +#define DW_UART_IIR_MASK (0x0E) +#define DW_UART_IIR_READ_FIFO_ENABLE (0xC0) + +/* Possible interrupt IIR_MASK values */ +#define DW_UART_IIR_MDM_STATUS (0x00) +#define DW_UART_IIR_XMIT_EMPTY (0x02) +#define DW_UART_IIR_DATA_AVAIL (0x04) +#define DW_UART_IIR_LINE_STATUS (0x06) +#define DW_UART_IIR_RX_TIMEOUT (0x0C) +#define DW_UART_IIR_INT_ID_MASK (0x0f) + +/* IIR WRITE */ +#define DW_UART_IIR_FIFO_ENABLE (0x01) +#define DW_UART_IIR_RCVR_FIFO_RESET (0x02) +#define DW_UART_IIR_XMIT_FIFO_RESET (0x04) +#define DW_UART_IIR_DMA_MODE_SELECT (0x08) +#define DW_UART_IIR_RCV_TRIGGER_MASK (0xC0) + +/* Values for IIR receive trigger */ +#define DW_UART_IIR_TRIGGER_LEVEL_1_CHAR (0x00) +#define DW_UART_IIR_TRIGGER_LEVEL_1_4_FULL (0x40) +#define DW_UART_IIR_TRIGGER_LEVEL_1_2_FULL (0x80) +#define DW_UART_IIR_TRIGGER_LEVEL_2_LESS_FULL (0xC0) +/** @} */ + +/** + * \name DesignWare UART HAL LCR Marcos + * \brief DesignWare UART hal LCR related macros + * @{ + */ +/* LCR */ +#define DW_UART_LCR_WORD_LEN_MASK (0x03) +#define DW_UART_LCR_STOP_BIT_MASK (0x04) +#define DW_UART_LCR_PARITY_MASK (0x38) +#define DW_UART_LCR_DPS_MASK (0x3F) +#define DW_UART_LCR_STICK_PARITY (0x20) +#define DW_UART_LCR_BREAK (0x40) +#define DW_UART_LCR_DLAB (0x80) + +/* Word length values */ +#define DW_UART_LCR_WORD_LEN5 (0x00) +#define DW_UART_LCR_WORD_LEN6 (0x01) +#define DW_UART_LCR_WORD_LEN7 (0x02) +#define DW_UART_LCR_WORD_LEN8 (0x03) + +/* stop bit values */ +#define DW_UART_LCR_1_STOP_BIT (0x00) +#define DW_UART_LCR_1D5_STOP_BIT (0x04) +#define DW_UART_LCR_2_STOP_BIT (0x04) + +/* Parity bit values */ +#define DW_UART_LCR_PARITY_NONE (0x00) +#define DW_UART_LCR_PARITY_ODD (0x08) +#define DW_UART_LCR_PARITY_EVEN (0x18) +#define DW_UART_LCR_PARITY_MARK (0x28) +#define DW_UART_LCR_PARITY_SPACE (0x38) + +/** @} */ + +/** + * \name DesignWare UART HAL MCR Marcos + * \brief DesignWare UART hal MCR related macros + * @{ + */ +/* MCR */ +#define DW_UART_MCR_DTR (0x01) +#define DW_UART_MCR_RTS (0x02) +#define DW_UART_MCR_LOOPBACK (0x10) +#define DW_UART_MCR_AFCE (0x20) +#define DW_UART_MCR_SIRE (0x40) +/** @} */ + +/** + * \name DesignWare UART HAL LSR Marcos + * \brief DesignWare UART hal LSR related macros + * @{ + */ +/* LSR */ +#define DW_UART_LSR_DR (0x01) +#define DW_UART_LSR_OVERRUN (0x02) +#define DW_UART_LSR_PARITYERR (0x04) +#define DW_UART_LSR_FRAMEERR (0x08) +#define DW_UART_LSR_BREAKRCVD (0x10) +#define DW_UART_LSR_TXD_EMPTY (0x20) +#define DW_UART_LSR_TX_STATUS (0x40) +#define DW_UART_LSR_RX_FIFOERR (0x80) +/** @} */ + +/** + * \name DesignWare UART HAL MSR Marcos + * \brief DesignWare UART hal MSR related macros + * @{ + */ +/* MSR */ +#define DW_UART_MSR_DCTS (0x01) +#define DW_UART_MSR_DDSR (0x02) +#define DW_UART_MSR_TERI (0x04) +#define DW_UART_MSR_DDCD (0x08) +#define DW_UART_MSR_CTS (0x10) +#define DW_UART_MSR_DSR (0x20) +#define DW_UART_MSR_RIC (0x40) +#define DW_UART_MSR_DCD (0x80) +/** @} */ + +/** + * \name DesignWare UART HAL FCR Marcos + * \brief DesignWare UART hal FCR related macros + * @{ + */ +/* FCR */ +#define DW_UART_FCR_FEN (0x01) +#define DW_UART_FCR_RFR (0x02) +#define DW_UART_FCR_TFR (0x04) +#define DW_UART_FCR_DMS (0x08) +#define DW_UART_FCR_RTL (0xC0) +/** @} */ + +/** + * \name DesignWare UART HAL USR Marcos + * \brief DesignWare UART hal USR related macros + * @{ + */ +/* USR */ +#define DW_UART_USR_BUSY (0x01) +#define DW_UART_USR_TFNF (0x02) +#define DW_UART_USR_TFE (0x04) +#define DW_UART_USR_RFNE (0x08) +#define DW_UART_USR_RFF (0x10) +/** @} */ + +/** + * \name DesignWare UART HAL SFE Marcos + * \brief DesignWare UART hal SFE related macros + * @{ + */ +/* SFE */ +#define DW_UART_SFE_SHADOW_FIFO_ENABLE (0x01) +/** @} */ + +/** + * \name DesignWare UART HAL SRR Marcos + * \brief DesignWare UART hal SRR related macros + * @{ + */ +/* SRR */ +#define DW_UART_SRR_UR (0x01) +#define DW_UART_SRR_RFR (0x02) +#define DW_UART_SRR_XFR (0x04) +/** @} */ + +/** + * \name DesignWare UART HAL SRT Marcos + * \brief DesignWare UART hal SRT related macros + * @{ + */ +/* SRT */ +#define DW_UART_SRT_TRIGGER_LEVEL_1_CHAR (0x00) +#define DW_UART_SRT_TRIGGER_LEVEL_1_4_FULL (0x01) +#define DW_UART_SRT_TRIGGER_LEVEL_1_2_FULL (0x02) +#define DW_UART_SRT_TRIGGER_LEVEL_2_LESS_FULL (0x03) +/** @} */ + +/** + * \name DesignWare UART HAL STET Marcos + * \brief DesignWare UART hal STET related macros + * @{ + */ +/* STET*/ +#define DW_UART_STET_FIFO_EMPTY (0x00) +#define DW_UART_STET_2_CHARS_IN_FIFO (0x01) +#define DW_UART_STET_1_4_FULL (0x02) +#define DW_UART_STET_1_2_FULL (0x03) +/** @} */ + +/** + * \name DesignWare UART HAL CPR Marcos + * \brief DesignWare UART hal CPR related macros + * @{ + */ +/* CPR*/ +#define DW_UART_CPR_FIFO_STAT (1<<10) +#define DW_UART_CPR_FIFO_MODE_OFS (16) +#define DW_UART_CPR_FIFO_MODE_MASK (0xFF) +#define DW_UART_CPR_FIFO_MODE (0xFF0000) +/** @} */ + +#endif /* _DEVICE_DW_UART_HAL_H_ */ diff --git a/hw/mcu/arc/src/ext/sdk/device/device_hal/inc/dev_common.h b/hw/mcu/arc/src/ext/sdk/device/device_hal/inc/dev_common.h new file mode 100644 index 000000000..623d54a61 --- /dev/null +++ b/hw/mcu/arc/src/ext/sdk/device/device_hal/inc/dev_common.h @@ -0,0 +1,173 @@ +/* ------------------------------------------ + * Copyright (c) 2016, Synopsys, Inc. All rights reserved. + + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + + * 1) Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + + * 2) 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. + + * 3) Neither the name of the Synopsys, Inc., nor the names of its contributors may + * be used to endorse or promote products derived from this software without + * specific prior written permission. + + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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. + * + * \version 2016.05 + * \date 2014-06-16 + * \author Huaqi Fang(Huaqi.Fang@synopsys.com) +--------------------------------------------- */ + +/** + * \defgroup DEVICE_HAL_COMMON Common Device Layer Definitions + * \ingroup DEVICE_HAL_DEF + * \brief common definitions for device layer (\ref dev_common.h) + * + * @{ + * + * \file + * \brief header file to define common definitions for device layer + * \details Here in this file provide definitions that need by other + * devices in device layer + */ + +#ifndef _DEVICE_HAL_COMMON_H_ +#define _DEVICE_HAL_COMMON_H_ + +#include + +/** + * \defgroup DEVICE_HAL_COMMON_DEVSTATE Common Device State + * \ingroup DEVICE_HAL_COMMON + * \brief definitions for device state + * \details here defines macros for device open/close, + * device working good/error, used in + * \ref DEVICE_HAL_UART, \ref DEVICE_HAL_SPI, + * \ref DEVICE_HAL_IIC, \ref DEVICE_HAL_GPIO + * @{ + */ +/* + * macros for device open and close state + */ +#define DEV_CLOSED (0) /*!< Indicate that device was closed */ +#define DEV_OPENED (1) /*!< Indicate that the device was opened */ + +/* + * macros for device good and error state + */ +#define DEV_GOOD (0) /*!< Indicate device is good */ +#define DEV_ERROR (1) /*!< Indicate device error */ +/** @} */ + +/** + * \defgroup DEVICE_HAL_COMMON_DEVMTHD Common Device Working Method + * \ingroup DEVICE_HAL_COMMON + * \brief definitions for device working method(interrupt or poll) + * \details here defines macros for working method, + * interrupt or poll method,used in + * \ref DEVICE_HAL_UART, \ref DEVICE_HAL_SPI, + * \ref DEVICE_HAL_IIC, \ref DEVICE_HAL_GPIO + * @{ + */ +/* + * macros for device working method + */ +#define DEV_POLL_METHOD (0) /*!< Indicate that the device running in poll method */ +#define DEV_INTERRUPT_METHOD (1) /*!< Indicate that the device running in interrupt method */ +/** @} */ + +/** + * \defgroup DEVICE_HAL_COMMON_DEVMODE Common Device Working Mode + * \ingroup DEVICE_HAL_COMMON + * \brief definitions for device working mode(master or slave) + * \details here defines macros for working mode, + * Master or Slave mode,used in + * \ref DEV_HAL_IIC, \ref DEV_HAL_SPI. + * @{ + */ +/* + * macros for device working mode + */ +#define DEV_MASTER_MODE (0) /*!< Indicate that the device working as master */ +#define DEV_SLAVE_MODE (1) /*!< Indicate that the device working as slave */ +/** @} */ + +/** + * \defgroup DEVICE_HAL_COMMON_DEVSTATUS Common Device Status + * \ingroup DEVICE_HAL_COMMON + * \brief definitions for device status, 1 bit for 1 function + * @{ + */ +#define DEV_DISABLED (0) /*!< Bit 0 for device enabled state, disabled */ +#define DEV_ENABLED (1<<0) /*!< Bit 0 for device enabled state, enabled */ +#define DEV_IN_TX (1<<1) /*!< Bit 1 for device in transmit state */ +#define DEV_IN_RX (1<<2) /*!< Bit 2 for device in receive state */ +#define DEV_IN_XFER (1<<3) /*!< Bit 3 for device in transfer state */ +#define DEV_IN_TX_ABRT (1<<4) /*!< Bit 4 for device in transmit abort state */ +#define DEV_IN_RX_ABRT (1<<5) /*!< Bit 5 for device in receive abort state */ +#define DEV_IN_XFER_ABRT (1<<6) /*!< Bit 6 for device in transfer abort state */ +/** @} */ + +/** + * \defgroup DEVICE_HAL_COMMON_DEFCMD Common Device Defining Command + * \ingroup DEVICE_HAL_COMMON + * \brief definitions for defining command code + * \details here defines macros to define command code, + * in system code, use \ref DEV_SET_SYSCMD to define command code. + * in user code, use \ref DEV_SET_USRCMD to define command code. + * So that there will be no conflicts in system and user defined command code. + * this used used in + * \ref DEVICE_HAL_UART, \ref DEVICE_HAL_SPI, + * \ref DEVICE_HAL_IIC, \ref DEVICE_HAL_GPIO, + * and in user code + * @{ + */ +/* + * macros for control command base + */ +#define DEV_SYS_CMDBSE (0x00000000) /*!< default system device control command base(defined by embARC) */ +#define DEV_USR_CMDBSE (0x80000000) /*!< default user device control command base(defined by user) in user implementing */ +#define DEV_SET_SYSCMD(cmd) (DEV_SYS_CMDBSE|(cmd)) /*!< set device system control command */ +#define DEV_SET_USRCMD(cmd) (DEV_USR_CMDBSE|(cmd)) /*!< set device user control command */ + +#define CONV2VOID(param) ((void *)(param)) /*!< convert param into void * type */ +/** @} */ + +/** + * Common Device Buffer Structure + */ +typedef struct dev_buffer { + void *buf; /*!< buffer pointer */ + uint32_t len; /*!< buffer length in bytes */ + uint32_t ofs; /*!< current offset in buffer */ +} DEV_BUFFER; + +/** Init device buffer */ +#define DEV_BUFFER_INIT(devbuf, buffer, size) { \ + (devbuf)->buf = (void *)(buffer); \ + (devbuf)->len = (uint32_t)(size); \ + (devbuf)->ofs = (uint32_t)(0); \ + } + +/** + * Device callback function typedef. + * This is usually used in device callback settings, + * and \ptr should be the device object pointer, + * such as DEV_IIC * */ +typedef void (*DEV_CALLBACK) (void *ptr); + +/** @} */ +#endif /* _DEVICE_HAL_COMMON_H_ */ diff --git a/hw/mcu/arc/src/ext/sdk/device/device_hal/inc/dev_gpio.h b/hw/mcu/arc/src/ext/sdk/device/device_hal/inc/dev_gpio.h new file mode 100644 index 000000000..290fd313a --- /dev/null +++ b/hw/mcu/arc/src/ext/sdk/device/device_hal/inc/dev_gpio.h @@ -0,0 +1,424 @@ +/* ------------------------------------------ + * Copyright (c) 2016, Synopsys, Inc. All rights reserved. + + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + + * 1) Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + + * 2) 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. + + * 3) Neither the name of the Synopsys, Inc., nor the names of its contributors may + * be used to endorse or promote products derived from this software without + * specific prior written permission. + + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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. + * + * \version 2016.05 + * \date 2014-06-17 + * \author Huaqi Fang(Huaqi.Fang@synopsys.com) +--------------------------------------------- */ + +/** + * \defgroup DEVICE_HAL_GPIO GPIO Device HAL Interface + * \ingroup DEVICE_HAL_DEF + * \brief definitions for gpio device hardware layer (\ref dev_gpio.h) + * \details provide interfaces for gpio driver to implement + * Here is a diagram for the gpio interface. + * + * \htmlonly + *
+ *
+ * GPIO Device HAL Interface Diagram + *

GPIO Device HAL Interface Diagram

+ *
+ *
+ * \endhtmlonly + * + * @{ + * + * \file + * \brief gpio device hardware layer definitions + * \details Provide common definitions for gpio device, + * then the software developer can develop gpio driver + * following these definitions, and the applications + * can directly call this definition to realize functions + * + */ + +#ifndef _DEVICE_HAL_GPIO_H_ +#define _DEVICE_HAL_GPIO_H_ + +#include "device/device_hal/inc/dev_common.h" + +/** + * \defgroup DEVICE_HAL_GPIO_DEFDIR GPIO Port Direction Definition + * \ingroup DEVICE_HAL_GPIO + * \brief Define macros to indicate gpio directions + * @{ + */ +/* + * defines for gpio directions + */ +#define GPIO_DIR_INPUT (0) /*!< gpio works as input */ +#define GPIO_DIR_OUTPUT (1) /*!< gpio works as output */ +/** @} */ + +/** + * \defgroup DEVICE_HAL_GPIO_CTRLCMD GPIO Device Control Commands + * \ingroup DEVICE_HAL_GPIO + * \brief Definitions for gpio control command, used in \ref dev_gpio::gpio_control "GPIO IO Control" + * \details These commands defined here can be used in user code directly. + * - Parameters Usage + * - For passing parameters like integer, just use uint32_t/int32_t to directly pass values + * - For passing parameters for a structure, please use pointer to pass values + * - For getting some data, please use pointer to store the return data + * - Common Return Values + * - \ref E_OK, Control device successfully + * - \ref E_CLSED, Device is not opened + * - \ref E_OBJ, Device object is not valid or not exists + * - \ref E_PAR, Parameter is not valid for current control command + * - \ref E_SYS, Control device failed, due to hardware issues such as device is disabled + * - \ref E_NOSPT, Control command is not supported or not valid + * @{ + */ +/** + * Set the \ref dev_gpio_info::direction "direction" of masked bits of gpio port into \ref GPIO_DIR_INPUT "input" + * - Param type : uint32_t + * - Param usage : 1 in each bit will be masked. + * - Return value explanation : + */ +#define GPIO_CMD_SET_BIT_DIR_INPUT DEV_SET_SYSCMD(0) +/** + * Set the \ref dev_gpio_info::direction "direction" of masked bits of gpio port into \ref GPIO_DIR_OUTPUT "output" + * - Param type : uint32_t + * - Param usage : 1 in each bit will be masked. + * - Return value explanation : + */ +#define GPIO_CMD_SET_BIT_DIR_OUTPUT DEV_SET_SYSCMD(1) +/** + * Get \ref dev_gpio_info::direction "gpio port direction". + * - Param type : uint32_t + * - Param usage : 1 bit for 1 bit of gpio port, 0 for input, 1 for output + * - Return value explanation : + */ +#define GPIO_CMD_GET_BIT_DIR DEV_SET_SYSCMD(2) +/** + * Set gpio interrupt configuration for each bit. + * - Param type : \ref DEV_GPIO_INT_CFG * + * - Param usage : store gpio interrupt configuration for each bit. + * - Return value explanation : + */ +#define GPIO_CMD_SET_BIT_INT_CFG DEV_SET_SYSCMD(3) +/** + * Get gpio interrupt configuration for each bit. + * - Param type : \ref DEV_GPIO_INT_CFG * + * - Param usage : First set int_bit_mask in DEV_GPIO_INT_CFG structure to + * the mask of which bit of GPIO you want to get. And the interrupt configuration + * will be stored in the structure DEV_GPIO_INT_CFG, each bit stand for each bit of port. + * - Return value explanation : + */ +#define GPIO_CMD_GET_BIT_INT_CFG DEV_SET_SYSCMD(4) +/** + * Set gpio service routine for each bit. + * - Param type : \ref DEV_GPIO_BIT_ISR * + * - Param usage : store gpio handler information for each bit, int handler's param will be DEV_GPIO *. + * - Return value explanation : + */ +#define GPIO_CMD_SET_BIT_ISR DEV_SET_SYSCMD(5) +/** + * Get gpio service routine for each bit. + * - Param type : \ref DEV_GPIO_BIT_ISR * + * - Param usage : By passing int_bit_ofs in DEV_GPIO_BIT_ISR, + * it will return interrupt handler for this bit and store it in int_bit_handler. + * - Return value explanation : + */ +#define GPIO_CMD_GET_BIT_ISR DEV_SET_SYSCMD(6) +/** + * Enable gpio interrupt of the masked bits. + * - Param type : uint32_t + * - Param usage : 1 in each bit will be masked. + * - Return value explanation : + */ +#define GPIO_CMD_ENA_BIT_INT DEV_SET_SYSCMD(7) +/** + * Disable gpio interrupt of the masked bits. + * - Param type : uint32_t + * - Param usage : 1 in each bit will be masked. + * - Return value explanation : + */ +#define GPIO_CMD_DIS_BIT_INT DEV_SET_SYSCMD(8) +/** + * Get \ref dev_gpio_info::method "gpio interrupt enable status". + * - Param type : uint32_t * + * - Param usage : 1 bit for 1 bit of gpio port, 0 for poll, 1 for interrupt + * - Return value explanation : + */ +#define GPIO_CMD_GET_BIT_MTHD DEV_SET_SYSCMD(9) +/* @} */ + +/** + * \defgroup DEVICE_HAL_GPIO_INT_CFG_SET GPIO Device Int Configuration Settings + * \ingroup DEVICE_HAL_GPIO + * \brief definition of gpio interrupt type + * @{ + */ + +/* GPIO Mask Defintions */ +/** Mask none bits of the max 32bits */ +#define GPIO_BITS_MASK_NONE (0) +/** Mask all bits of the max 32bits */ +#define GPIO_BITS_MASK_ALL (0XFFFFFFFF) + +/* GPIO Interrupt Type Related Definitions */ + +/** Level sensitive interrupt type for 1 bit */ +#define GPIO_INT_LEVEL_TRIG (0) +/** Edge sensitive interrupt type for 1 bit */ +#define GPIO_INT_EDGE_TRIG (1) +/** Level sensitive interrupt type for all 32 bits */ +#define GPIO_INT_LEVEL_TRIG_ALL (0) +/** Edge sensitive interrupt type for all 32 bits */ +#define GPIO_INT_EDGE_TRIG_ALL (0XFFFFFFFF) + +/* For bit settings */ +/** Set bit interrupt type of gpio into level sensitive */ +#define GPIO_INT_BIT_LEVEL_TRIG(bit_ofs) (GPIO_INT_LEVEL_TRIG<<(bit_ofs)) +/** Set bit interrupt type of gpio into edge sensitive */ +#define GPIO_INT_BIT_EDGE_TRIG(bit_ofs) (GPIO_INT_EDGE_TRIG<<(bit_ofs)) +/* For bits settings */ +/** Set interrupt type of masked bits of gpio into level sensitive */ +#define GPIO_INT_BITS_LEVEL_TRIG(bit_mask) (GPIO_INT_LEVEL_TRIG_ALL&(bit_mask)) +/** Set bit interrupt type of gpio into edge sensitive */ +#define GPIO_INT_BITS_EDGE_TRIG(bit_mask) (GPIO_INT_EDGE_TRIG_ALL&(bit_mask)) + +/* GPIO Interrupt Polarity Related Definitions */ + +/** GPIO Interrupt polarity type enum */ +typedef enum gpio_int_polarity { + /* Polarity for 1 bit */ + GPIO_INT_ACTIVE_LOW = 0, /*!< Active low for level-sensitive interrupt for 1 bit */ + GPIO_INT_FALLING_EDGE = 0, /*!< Falling-edge for edge-sensitive interrupt for 1 bit */ + GPIO_INT_ACTIVE_HIGH = 1, /*!< Active high for level-sensitive interrupt for 1 bit */ + GPIO_INI_RISING_EDGE = 1, /*!< Rising-edge for edge-sensitive interrupt for 1 bit */ + /* Polartiy for all 32 bits */ + GPIO_INT_ACTIVE_LOW_ALL = 0, /*!< Active low for level-sensitive interrupt for all bits */ + GPIO_INT_FALLING_EDGE_ALL = 0, /*!< Falling-edge for edge-sensitive interrupt for all bits */ + GPIO_INT_ACTIVE_HIGH_ALL = 0XFFFFFFFF, /*!< Active high for level-sensitive interrupt for all bits */ + GPIO_INI_RISING_EDGE_ALL = 0XFFFFFFFF /*!< Rising-edge for edge-sensitive interrupt for all bits */ +} GPIO_INT_POLARITY; + +/* For bit settings */ +/** Set bit polarity of gpio into active low */ +#define GPIO_INT_BIT_POL_ACT_LOW(bit_ofs) (GPIO_INT_ACTIVE_LOW<<(bit_ofs)) +/** Set bit polarity of gpio into active high */ +#define GPIO_INT_BIT_POL_ACT_HIGH(bit_ofs) (GPIO_INT_ACTIVE_HIGH<<(bit_ofs)) +/** Set bit polarity of gpio into falling edge */ +#define GPIO_INT_BIT_POL_FALL_EDGE(bit_ofs) (GPIO_INT_FALLING_EDGE<<(bit_ofs)) +/** Set bit polarity of gpio into rising edge */ +#define GPIO_INT_BIT_POL_RISE_EDGE(bit_ofs) (GPIO_INI_RISING_EDGE<<(bit_ofs)) + +/* For bits settings */ +/** Set polarity of masked bits of gpio into active low */ +#define GPIO_INT_BITS_POL_ACT_LOW(bit_mask) (GPIO_INT_ACTIVE_LOW_ALL&(bit_mask)) +/** Set polarity of masked bits of gpio into active high */ +#define GPIO_INT_BITS_POL_ACT_HIGH(bit_mask) (GPIO_INT_ACTIVE_HIGH_ALL&(bit_mask)) +/** Set polarity of masked bits of gpio into falling edge */ +#define GPIO_INT_BITS_POL_FALL_EDGE(bit_mask) (GPIO_INT_FALLING_EDGE_ALL&(bit_mask)) +/** Set polarity of masked bits of gpio into rising edge */ +#define GPIO_INT_BITS_POL_RISE_EDGE(bit_mask) (GPIO_INI_RISING_EDGE_ALL&(bit_mask)) + +/* GPIO Interrupt Debounce Related Definitions */ + +/* For bit settings */ +/** Disable debounce circuitry for 1 bit */ +#define GPIO_INT_NO_DEBOUNCE (0) +/** Enable debounce circuitry for 1 bit */ +#define GPIO_INT_DEBOUNCE (1) + +/* For bits settings */ +/** Disable debounce circuitry for all bits */ +#define GPIO_INT_NO_DEBOUNCE_ALL (0) +/** Enable debounce circuitry for all bits */ +#define GPIO_INT_DEBOUNCE_ALL (0XFFFFFFFF) + +/* For bit settings */ +/** Set bit interrupt debounce of gpio into enabled */ +#define GPIO_INT_BIT_ENA_DEBOUNCE(bit_ofs) (GPIO_INT_DEBOUNCE<<(bit_ofs)) +/** Set bit interrupt debounce of gpio into disabled */ +#define GPIO_INT_BIT_DIS_DEBOUNCE(bit_ofs) (GPIO_INT_NO_DEBOUNCE<<(bit_ofs)) +/* For bits settings */ +/** Set bit interrupt debounce of gpio into enabled */ +#define GPIO_INT_BITS_ENA_DEBOUNCE(bit_mask) (GPIO_INT_DEBOUNCE_ALL&(bit_mask)) +/** Set bit interrupt debounce of gpio into disabled */ +#define GPIO_INT_BITS_DIS_DEBOUNCE(bit_mask) (GPIO_INT_NO_DEBOUNCE_ALL&(bit_mask)) + +/** GPIO interrupt configuration */ +typedef struct dev_gpio_int_cfg { + uint32_t int_bit_mask; /*!< interrupt bit mask for gpio */ + uint32_t int_bit_type; /*!< \ref GPIO_INT_LEVEL_TRIG "level sensitive" or \ref GPIO_INT_EDGE_TRIG "edge sensitive" for each gpio bit */ + uint32_t int_bit_polarity; /*!< active high or low, refer to \ref GPIO_INT_POLARITY for each gpio bit */ + uint32_t int_bit_debounce; /*!< \ref GPIO_INT_DEBOUNCE "enable" or \ref GPIO_INT_NO_DEBOUNCE "disable" debounce logic for each gpio bit */ +} DEV_GPIO_INT_CFG, * DEV_GPIO_INT_CFG_PTR; + +/** Default interrupt configuration for all gpio bits */ +static const DEV_GPIO_INT_CFG gpio_int_cfg_default = \ + {GPIO_BITS_MASK_ALL, GPIO_INT_LEVEL_TRIG_ALL, \ + GPIO_INT_ACTIVE_LOW_ALL, GPIO_INT_NO_DEBOUNCE_ALL}; + +/** GPIO interrupt handler or Interrupt Service Routine(ISR) */ +typedef void (*DEV_GPIO_HANDLER) (void *ptr); + +/** interrupt handler for each port bit */ +typedef struct dev_gpio_bit_isr { + uint32_t int_bit_ofs; /*!< int bit offset */ + DEV_GPIO_HANDLER int_bit_handler; /*!< interrupt handler */ +} DEV_GPIO_BIT_ISR, * DEV_GPIO_BIT_ISR_PTR; +/* @} */ + +/** + * \defgroup DEVICE_HAL_GPIO_DEVSTRUCT GPIO Device Interface Definition + * \ingroup DEVICE_HAL_GPIO + * \brief contains definitions of gpio device structure. + * \details This structure will be used in user implemented code, which was called + * \ref DEVICE_IMPL "Device Driver Implement Layer" for gpio to use in implementation code. + * Application developer should use the GPIO API provided here to access to GPIO devices. + * BSP developer should follow the API definition to implement GPIO device drivers. + * @{ + */ +/** + * \brief gpio information struct definition + * \details informations about gpio open count, working status + * gpio registers and control block, gpio io direction and interrupt/poll for each bit of gpio + * \note Only available for gpio with max 32bits + */ +typedef struct dev_gpio_info { + void *gpio_ctrl; /*!< gpio control related pointer, implemented by bsp developer, and this should be set during gpio object implementation */ + uint32_t opn_cnt; /*!< gpio open count, open it will increase 1, close it will decrease 1, 0 for close, >0 for open */ + uint32_t direction; /*!< each bit direction of this GPIO, default all \ref GPIO_DIR_INPUT "input" for first open */ + uint32_t method; /*!< int/poll method for each bit of GPIO, 0 for poll, 1 for interrupt, default all \ref DEV_POLL_METHOD "poll" for first open */ + void * extra; /*!< a extra pointer to get hook to applications which should not used by bsp developer, + this should be NULL for first open and you can \ref DEV_GPIO_INFO_SET_EXTRA_OBJECT "set" + or \ref DEV_GPIO_INFO_GET_EXTRA_OBJECT "get" the extra information pointer */ +} DEV_GPIO_INFO, * DEV_GPIO_INFO_PTR; +/** Set extra information pointer of gpio info */ +#define DEV_GPIO_INFO_SET_EXTRA_OBJECT(gpio_info_ptr, extra_info) (gpio_info_ptr)->extra = (void *)(extra_info) +/** Get extra information pointer of gpio info */ +#define DEV_GPIO_INFO_GET_EXTRA_OBJECT(gpio_info_ptr) ((gpio_info_ptr)->extra) + +/** Method of all gpio bits set to poll */ +#define DEV_GPIO_BITS_MTHD_POLL (0) +/** Method of all gpio bits set to interrupt */ +#define DEV_GPIO_BITS_MTHD_INTERRUPT (0xFFFFFFFF) +/** Default method of all gpio bits should be poll for first open */ +#define DEV_GPIO_BITS_MTHD_DEFAULT (DEV_GPIO_BITS_MTHD_POLL) + +/** + * \brief gpio device interface definition + * \details define gpio device interface, like gpio information structure, + * fuctions to open/close/control gpio, write or read data via gpio + * \note all this details are implemented by user in user porting code + */ +typedef struct dev_gpio { + DEV_GPIO_INFO gpio_info; /*!< gpio device information */ + int32_t (*gpio_open) (uint32_t dir); /*!< open gpio device with pre-defined gpio direction */ + int32_t (*gpio_close) (void); /*!< close gpio device */ + int32_t (*gpio_control) (uint32_t ctrl_cmd, void *param); /*!< control gpio device */ + int32_t (*gpio_write) (uint32_t val, uint32_t mask); /*!< write gpio device with val, only write the masked bits */ + int32_t (*gpio_read) (uint32_t *val, uint32_t mask); /*!< read gpio device val, only read the masked bits */ +} DEV_GPIO, * DEV_GPIO_PTR; + +/** + * \fn int32_t (* dev_gpio::gpio_open) (uint32_t dir) + * \details Open a gpio device with pre-defined io direction. + * \param[in] dir gpio direction for each bit + * \retval E_OK Open successfully without any issues + * \retval E_OPNED If device was opened before with different parameters, + * then just increase the \ref dev_gpio_info::opn_cnt "opn_cnt" and return \ref E_OPNED + * \retval E_OBJ Device object is not valid + * \retval E_PAR Parameter is not valid + * \retval E_NOSPT Open settings are not supported + */ + +/** + * \fn int32_t (* dev_gpio::gpio_close) (void) + * \details Close an gpio device, just decrease the \ref dev_gpio_info::opn_cnt "opn_cnt", + * if \ref dev_gpio_info::opn_cnt "opn_cnt" equals 0, then close the device + * \retval E_OK Close successfully without any issues(including scenario that device is already closed) + * \retval E_OPNED Device is still opened, the device \ref dev_gpio_info::opn_cnt "opn_cnt" decreased by 1 + * \retval E_OBJ Device object is not valid + */ + +/** + * \fn int32_t (* dev_gpio::gpio_control) (uint32_t ctrl_cmd, void *param) + * \details Control an gpio device by \ref ctrl_cmd, with passed \ref param. + * you can control gpio device using predefined gpio control commands defined using \ref DEV_SET_SYSCMD + * (which must be implemented by bsp developer), such as \ref GPIO_CMD_SET_BIT_DIR_INPUT + * "change masked gpio direction to input", and \ref DEVICE_HAL_GPIO_CTRLCMD "more". + * And you can also control gpio device using your own specified commands defined using \ref DEV_SET_USRCMD, + * but these specified commands should be defined in your own gpio device driver implementation. + * \param[in] ctrl_cmd \ref DEVICE_HAL_GPIO_CTRLCMD "control command", to change or get some thing related to gpio + * \param[in,out] param parameters that maybe argument of the command, or return values of the command + * \retval E_OK Control device successfully + * \retval E_CLSED Device is not opened + * \retval E_OBJ Device object is not valid or not exists + * \retval E_PAR Parameter is not valid for current control command + * \retval E_SYS Control device failed, due to hardware issues + * \retval E_CTX Control device failed, due to different reasons like in transfer state + * \retval E_NOSPT Control command is not supported or not valid, such as interrupt is not supported + */ + +/** + * \fn int32_t (* dev_gpio::gpio_write) (uint32_t val, uint32_t mask) + * \details Write gpio with \ref val, and only change the masked bits of gpio. + * \param[in] val the data that need to write to gpio + * \param[in] mask gpio bit mask + * \retval E_OK Write gpio with specified value successfully + * \retval E_OBJ Device object is not valid or not exists + * \retval E_PAR Parameter is not valid + */ + +/** + * \fn int32_t (* dev_gpio::gpio_read) (uint32_t *val, uint32_t mask) + * \details Read the masked gpio value + * \param[out] val pointer to data need to read from gpio + * \param[in] mask gpio bit mask + * \retval E_OK Read gpio data successfully + * \retval E_OBJ Device object is not valid or not exists + * \retval E_PAR Parameter is not valid + */ + +/** @} */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief get an \ref dev_gpio "gpio device" by gpio device id. + * For how to use gpio device hal refer to \ref dev_gpio "Functions in gpio device structure" + * \param[in] gpio_id id of gpio, defined by user + * \retval !NULL pointer to an \ref dev_gpio "gpio device structure" + * \retval NULL failed to find the gpio device by \ref gpio_id + * \note need to implemented by user in user code + */ +extern DEV_GPIO_PTR gpio_get_dev(int32_t gpio_id); + +#ifdef __cplusplus +} +#endif + +/** @} */ +#endif /* _DEVICE_HAL_GPIO_H_ */ diff --git a/hw/mcu/arc/src/ext/sdk/device/device_hal/inc/dev_iic.h b/hw/mcu/arc/src/ext/sdk/device/device_hal/inc/dev_iic.h new file mode 100644 index 000000000..14106671f --- /dev/null +++ b/hw/mcu/arc/src/ext/sdk/device/device_hal/inc/dev_iic.h @@ -0,0 +1,526 @@ +/* ------------------------------------------ + * Copyright (c) 2017, Synopsys, Inc. All rights reserved. + + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + + * 1) Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + + * 2) 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. + + * 3) Neither the name of the Synopsys, Inc., nor the names of its contributors may + * be used to endorse or promote products derived from this software without + * specific prior written permission. + + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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. + * + * \version 2017.03 + * \date 2014-06-16 + * \author Huaqi Fang(Huaqi.Fang@synopsys.com) +--------------------------------------------- */ + +/** + * \defgroup DEVICE_HAL_IIC IIC Device HAL Interface + * \ingroup DEVICE_HAL_DEF + * \brief definitions for iic device hardware layer (\ref dev_iic.h) + * \details provide interfaces for iic driver to implement + * Here is a diagram for the iic interface. + * + * \htmlonly + *
+ *
+ * IIC Device HAL Interface Diagram + *

IIC Device HAL Interface Diagram

+ *
+ *
+ * \endhtmlonly + * + * @{ + * + * \file + * \brief iic device hardware layer definitions + * \details provide common definitions for iic device, + * then software developer can develop iic driver + * following this definitions, and the applications + * can directly call this definition to realize functions + */ + +#ifndef _DEVICE_HAL_IIC_H_ +#define _DEVICE_HAL_IIC_H_ + +#include "device/device_hal/inc/dev_common.h" + +/** + * \defgroup DEVICE_HAL_IIC_CFG IIC Related Configurations + * \ingroup DEVICE_HAL_IIC + * \brief Macros for IIC device related configurations. + * @{ + */ +/** IIC Bus possible speed modes */ +typedef enum iic_speed_mode { + IIC_SPEED_STANDARD = 0, /*!< Bidirectional, Standard-mode (Sm), with a bit rate up to 100 kbit/s */ + IIC_SPEED_FAST = 1, /*!< Bidirectional, Fast-mode (Fm), with a bit rate up to 400 kbit/s */ + IIC_SPEED_FASTPLUS = 2, /*!< Bidirectional, Fast-mode Plus (Fm+), with a bit rate up to 1 Mbit/s */ + IIC_SPEED_HIGH = 3, /*!< Bidirectional, High-speed mode (Hs-mode), with a bit rate up to 3.4 Mbit/s */ + IIC_SPEED_ULTRA = 4 /*!< Unidirectional(Write only), Ultra Fast-mode (UFm), with a bit rate up to 5 Mbit/s */ +} IIC_SPEED_MODE; + +/** IIC next Condition */ +typedef enum iic_next_condtion { + IIC_MODE_STOP = 0, /*!< Send a STOP condition after write/read operation */ + IIC_MODE_RESTART = 1 /*!< Send a RESTART condition after write/read operation */ +} IIC_NEXT_CONDTION; + +/** IIC Error State */ +typedef enum iic_error_state { + IIC_ERR_NONE = 0, /*!< Currently in iic device free state */ + IIC_ERR_LOST_BUS = 1, /*!< Master or slave lost bus during operation */ + IIC_ERR_ADDR_NOACK = 2, /*!< Slave address is sent but not addressed by any slave devices */ + IIC_ERR_DATA_NOACK = 3, /*!< Data in transfer is not acked when it should be acked */ + IIC_ERR_TIMEOUT = 4, /*!< Transfer timeout, no more data is received or sent */ + IIC_ERR_MSTSTOP = 5, /*!< Slave received a STOP condition from master device */ + IIC_ERR_UNDEF = 6 /*!< Undefined error cases */ +} IIC_ERROR_STATE; + +/** IIC Working State */ +typedef enum iic_working_state { + IIC_FREE = 0, /*!< Currently in iic device free state */ + IIC_IN_TX = 1, /*!< Currently in iic master transmit state */ + IIC_IN_RX = 2 /*!< Currently in iic master receive state */ +} IIC_WORKING_STATE; + +/** IIC Addressing Mode */ +typedef enum iic_address_mode { + IIC_7BIT_ADDRESS = 0, /*!< Use 7bit address mode */ + IIC_10BIT_ADDRESS = 1 /*!< Use 10bit address mode */ +} IIC_ADDRESS_MODE; + +/** IIC Slave State */ +typedef enum iic_slave_state { + IIC_SLAVE_STATE_FREE = 0, /*!< None state, in free */ + IIC_SLAVE_STATE_START = (1<<1), /*!< Start or Restart condition, clear it when read */ + IIC_SLAVE_STATE_STOP = (1<<2), /*!< Stop condition, clear it when read */ + IIC_SLAVE_STATE_RD_REQ = (1<<3), /*!< Read request from master, this will trigger the slave transmit callback */ + IIC_SLAVE_STATE_RD_DONE = (1<<4), /*!< Read request done from master, clear it when read */ + IIC_SLAVE_STATE_WR_REQ = (1<<5), /*!< Write request from master, this will trigger the slave receive callback */ + IIC_SLAVE_STATE_GC_REQ = (1<<6), /*!< General call request from master */ + IIC_SLAVE_STATE_ERROR = (1<<7) /*!< Error, clear it when read */ +} IIC_SLAVE_STATE; + +/** 7bit IIC address mask */ +#define IIC_7BIT_ADDRESS_MASK (0x7F) +/** 10bit IIC address mask */ +#define IIC_10BIT_ADDRESS_MASK (0x3FF) +/** @} */ + +/** + * \defgroup DEVICE_HAL_IIC_CTRLCMD IIC Device Control Commands + * \ingroup DEVICE_HAL_IIC + * \brief Definitions for iic control command, used in \ref dev_iic::iic_control "IIC IO Control" + * \details These commands defined here can be used in user code directly. + * - Parameters Usage + * - For passing parameters like integer, just use uint32_t/int32_t to directly pass values + * - For passing parameters for a structure, please use pointer to pass values + * - For getting some data, please use pointer to store the return data + * - Common Return Values + * - \ref E_OK, Control device successfully + * - \ref E_CLSED, Device is not opened + * - \ref E_OBJ, Device object is not valid or not exists + * - \ref E_PAR, Parameter is not valid for current control command + * - \ref E_SYS, Control device failed, due to hardware issues such as device is disabled + * - \ref E_CTX, Control device failed, due to different reasons like in transfer state + * - \ref E_NOSPT, Control command is not supported or not valid + * @{ + */ + +/** Define IIC control commands for common usage */ +#define DEV_SET_IIC_SYSCMD(cmd) DEV_SET_SYSCMD((cmd)) +/** Define IIC control commands for master usage */ +#define DEV_SET_IIC_MST_SYSCMD(cmd) DEV_SET_SYSCMD(0x00004000|(cmd)) +/** Define IIC control commands for slave usage */ +#define DEV_SET_IIC_SLV_SYSCMD(cmd) DEV_SET_SYSCMD(0x00008000|(cmd)) + +/* ++++ Common commands for IIC Device ++++ */ +/** + * Get \ref dev_iic_info::status "current device status" + * - Param type : uint32_t * + * - Param usage : store result of current status + * - Return value explanation : + */ +#define IIC_CMD_GET_STATUS DEV_SET_IIC_SYSCMD(0) +/** + * Set \ref dev_iic_info::addr_mode "iic addressing mode". + * - Param type : uint32_t + * - Param usage : iic addressing mode, possible values can be found \ref IIC_ADDRESS_MODE "here" + * - Return value explanation : + */ +#define IIC_CMD_SET_ADDR_MODE DEV_SET_IIC_SYSCMD(1) +/** + * Set \ref dev_iic_cbs::tx_cb "iic transmit success callback" function + * when all required bytes are transmitted for interrupt method + * - Param type : \ref DEV_CALLBACK * or NULL + * - Param usage : transmit success callback function for iic + * - Return value explanation : + */ +#define IIC_CMD_SET_TXCB DEV_SET_IIC_SYSCMD(2) +/** + * Set \ref dev_iic_cbs::rx_cb "iic receive success callback" function + * when all required bytes are received for interrupt method + * - Param type : \ref DEV_CALLBACK * or NULL + * - Param usage : receive success callback function for iic + * - Return value explanation : + */ +#define IIC_CMD_SET_RXCB DEV_SET_IIC_SYSCMD(3) +/** + * Set \ref dev_iic_cbs::err_cb "iic transfer error callback" function + * when something error happened for interrupt method + * - Param type : \ref DEV_CALLBACK * or NULL + * - Param usage : transfer error callback function for iic + * - Return value explanation : + */ +#define IIC_CMD_SET_ERRCB DEV_SET_IIC_SYSCMD(4) +/** + * Set buffer for interrupt transmit, and it will set \ref dev_iic_info::tx_buf "tx_buf". + * - IIC master mode use case \n + * For master mode, if you set tx buffer to NULL, when tx interrupt is enabled and entered into tx interrupt, + * it will automatically disable the tx interrupt, so when you want to transfer something, you need to set the + * tx buffer to Non-NULL and enable tx interrupt, when the tx buffer is sent, it will disable the tx interrupt + * and call tx callback function if available. + * - IIC slave mode use case \n + * For slave mode, the tx buffer is not used, only tx callback function is used, and if tx callback is not set, + * then it will automatically disable the tx interrupt, if tx callback is set, it will call the tx callback function + * and you need to write or read in the tx callback function, to avoid meaningless waiting, you can use control command + * \ref IIC_CMD_GET_TXAVAIL to get how many bytes space existing in transmit fifo, and use iic_write to send the available + * bytes. + * - Param type : DEV_BUFFER * or NULL + * - Param usage : buffer structure pointer, if param is NULL, then it will set tx_buf to NULL + * - Return value explanation : + */ +#define IIC_CMD_SET_TXINT_BUF DEV_SET_IIC_SYSCMD(5) +/** + * Set buffer for interrupt receive, and it will set \ref dev_iic_info::rx_buf "rx_buf" + * - IIC master mode use case \n + * Similar to \ref IIC_CMD_SET_TXINT_BUF + * - IIC slave mode use case \n + * Similiar to \ref IIC_CMD_SET_TXINT_BUF + * - Param type : DEV_BUFFER * or NULL + * - Param usage : buffer structure pointer, if param is NULL, then it will set rx_buf to NULL + * - Return value explanation : + */ +#define IIC_CMD_SET_RXINT_BUF DEV_SET_IIC_SYSCMD(6) +/** + * Enable or disable transmit interrupt, + * for master mode, only one of tx and rx interrupt can be enabled, + * if tx interrupt is enabled, then rx interrupt can't be changed. + * - Param type : uint32_t + * - Param usage : enable(none-zero) or disable(zero) flag + * - Return value explanation : + */ +#define IIC_CMD_SET_TXINT DEV_SET_IIC_SYSCMD(7) +/** + * Enable or disable receive interrupt, + * for master mode, only one of tx and rx interrupt can be enabled, + * if rx interrupt is enabled, then tx interrupt can't be changed. + * - Param type : uint32_t + * - Param usage : enable(none-zero) or disable(zero) flag + * - Return value explanation : + */ +#define IIC_CMD_SET_RXINT DEV_SET_IIC_SYSCMD(8) +/** + * Abort current interrupt transmit operation if tx interrupt enabled, + * it will disable transmit interrupt, and set \ref DEV_IN_TX_ABRT + * in \ref dev_iic_info::status "status" variable, + * and call the transmit callback function, when tx callback is finished, + * it will clear \ref DEV_IN_TX_ABRT and return + * - Param type : NULL + * - Param usage : + * - Return value explanation : + */ +#define IIC_CMD_ABORT_TX DEV_SET_IIC_SYSCMD(9) +/** + * Abort current interrupt receive operation if rx interrupt enabled, + * it will disable receive interrupt, and set \ref DEV_IN_TX_ABRT + * in \ref dev_iic_info::status "status" variable, + * and call the receive callback function, when rx callback is finished, + * it will clear \ref DEV_IN_TX_ABRT and return + * - Param type : NULL + * - Param usage : + * - Return value explanation : + */ +#define IIC_CMD_ABORT_RX DEV_SET_IIC_SYSCMD(10) +/** + * Do a software reset for IIC device, it will stop current transfer, + * and clear error state and bring device to normal state, set next condition to STOP + * - Param type : NULL + * - Param usage : + * - Return value explanation : + */ +#define IIC_CMD_RESET DEV_SET_IIC_SYSCMD(11) +/** + * Flush iic device transmit buffer or fifo + * - Param type : NULL + * - Param usage : + * - Return value explanation : + */ +#define IIC_CMD_FLUSH_TX DEV_SET_IIC_SYSCMD(12) +/** + * Flush iic device receive buffer or fifo + * - Param type : NULL + * - Param usage : + * - Return value explanation : + */ +#define IIC_CMD_FLUSH_RX DEV_SET_IIC_SYSCMD(13) +/** + * Enable iic device + * - Param type : NULL + * - Param usage : param is not required + * - Return value explanation : + */ +#define IIC_CMD_ENA_DEV DEV_SET_IIC_SYSCMD(14) +/** + * Disable iic device, when device is disabled, + * only \ref IIC_CMD_ENA_DEV, \ref IIC_CMD_DIS_DEV, + * \ref IIC_CMD_GET_STATUS and \ref IIC_CMD_RESET + * commands can be executed, other commands will return \ref E_SYS + * - Param type : NULL + * - Param usage : param is not required + * - Return value explanation : + */ +#define IIC_CMD_DIS_DEV DEV_SET_IIC_SYSCMD(15) +/** + * Get how many bytes space in iic are available to transmit, + * this can be used in interrupt callback functions, + * cooperate with \ref dev_iic::iic_write "iic_write" API to realize non-blocked write + * - Param type : int32_t * + * - Param usage : store the write available bytes, > 0 for available bytes, 0 for not available + * - Return value explaination : + */ +#define IIC_CMD_GET_TXAVAIL DEV_SET_IIC_SYSCMD(16) +/** + * Get how many bytes in iic are available to receive, + * this can be used in interrupt callback functions, + * cooperate with \ref dev_iic::iic_read "iic_read" API to realize non-blocked read + * - Param type : int32_t * + * - Param usage : store the read available bytes, > 0 for available bytes, 0 for not available + * - Return value explanation : + */ +#define IIC_CMD_GET_RXAVAIL DEV_SET_IIC_SYSCMD(17) + +/* ++++ Master only commands for IIC Device ++++ */ +/** + * Set \ref dev_iic_info::speed_mode "iic speed mode". + * - Param type : uint32_t + * - Param usage : iic speed mode, possible values can be found \ref IIC_SPEED_MODE "here", + * and if passing mode is not supported, it will choose a lower supported speed mode + * - Return value explanation : + */ +#define IIC_CMD_MST_SET_SPEED_MODE DEV_SET_IIC_MST_SYSCMD(0) +/** + * Set next condition for following transmit or receive operation. + * For example, you can change next condition before iic_read or iic_write, + * then in iic_read/iic_write operation, it will send a STOP/RESTART condition + * after the last byte of this operation. For interrupt, this is similar. + * - Param type : uint32_t + * - Param usage : next condition can be \ref IIC_NEXT_CONDTION + * - Return value explanation : + */ +#define IIC_CMD_MST_SET_NEXT_COND DEV_SET_IIC_MST_SYSCMD(1) +/** + * Set target slave device address for selecting slave device + * - Param type : uint32_t + * - Param usage : target slave address value + * - Return value explanation : + */ +#define IIC_CMD_MST_SET_TAR_ADDR DEV_SET_IIC_MST_SYSCMD(2) + + +/* ++++ Slave only commands for IIC Device ++++ */ +/** + * Set slave address when working as slave iic device + * - Param type : uint32_t + * - Param usage : slave address value + * - Return value explanation : + */ +#define IIC_CMD_SLV_SET_SLV_ADDR DEV_SET_IIC_SLV_SYSCMD(0) +/** + * Get \ref iic_slave_state "slave state" when working as slave iic device + * - Param type : uint32_t * + * - Param usage : slave state + * - Return value explanation : + */ +#define IIC_CMD_SLV_GET_SLV_STATE DEV_SET_IIC_SLV_SYSCMD(1) + +/** @} */ + +/** + * \defgroup DEVICE_HAL_IIC_CALLBACK IIC Interrupt callback functions + * \ingroup DEVICE_HAL_IIC + * \brief callback function structure for IIC device + * @{ + */ +typedef struct dev_iic_cbs { + DEV_CALLBACK tx_cb; /*!< iic data transmit success required bytes callback */ + DEV_CALLBACK rx_cb; /*!< iic data receive success required bytes callback */ + DEV_CALLBACK err_cb; /*!< iic error callback */ +} DEV_IIC_CBS, *DEV_IIC_CBS_PTR; +/** @} */ + +/** + * \defgroup DEVICE_HAL_IIC_DEVSTRUCT IIC Device Structure + * \ingroup DEVICE_HAL_IIC + * \brief contains definitions of iic device structure. + * \details this structure will be used in user implemented code, which was called + * Device Driver Implement Layer for iic to realize in user code. + * @{ + */ +/** + * \brief iic information struct definition + * \details informations about iic open state, working state, + * baurate, iic registers, working method, interrupt number + */ +typedef struct dev_iic_info { + void *iic_ctrl; /*!< iic control related pointer, implemented by bsp developer, and this should be set during iic object implementation */ + uint32_t opn_cnt; /*!< iic open count, open it will increase 1, close it will decrease 1, 0 for close, >0 for open */ + uint32_t status; /*!< current working status, refer to \ref DEVICE_HAL_COMMON_DEVSTATUS, this should be \ref DEV_ENABLED for first open */ + uint32_t mode; /*!< current working mode, which can be \ref DEV_MASTER_MODE "master mode" or \ref DEV_SLAVE_MODE "slave mode" */ + uint32_t speed_mode; /*!< current working \ref IIC_SPEED_MODE "iic speed mode" */ + uint32_t cur_state; /*!< \ref IIC_WORKING_STATE "current working state for iic device", this should be \ref IIC_FREE for first open */ + uint32_t err_state; /*!< \ref IIC_ERROR_STATE "current error state for iic device", this should be \ref IIC_ERR_NONE for first open */ + uint32_t addr_mode; /*!< \ref IIC_ADDRESS_MODE "current addressing mode", this should be \ref IIC_7BIT_ADDRESS for first open */ + uint32_t slv_addr; /*!< slave address when working as slave iic device, this should be 0 for first open */ + uint32_t tar_addr; /*!< target slave device address when addressing that slave device, this should be 0 for first open */ + uint32_t next_cond; /*!< \ref IIC_NEXT_CONDTION "next condition for master transmit or receive", \ + possible values are STOP or RESTART, it should be STOP for first open */ + DEV_BUFFER tx_buf; /*!< transmit buffer via interrupt, this should be all zero for first open */ + DEV_BUFFER rx_buf; /*!< receive buffer via interrupt, this should be all zero for first open */ + DEV_IIC_CBS iic_cbs; /*!< iic callbacks, for both master and slave mode, this should be all NULL for first open */ + void *extra; /*!< a extra pointer to get hook to applications which should not used by bsp developer, + this should be NULL for first open and you can \ref DEV_IIC_INFO_SET_EXTRA_OBJECT "set" + or \ref DEV_IIC_INFO_GET_EXTRA_OBJECT "get" the extra information pointer */ +} DEV_IIC_INFO, * DEV_IIC_INFO_PTR; + +/** Set extra information pointer of iic info */ +#define DEV_IIC_INFO_SET_EXTRA_OBJECT(iic_info_ptr, extra_info) (iic_info_ptr)->extra = (void *)(extra_info) +/** Get extra information pointer of iic info */ +#define DEV_IIC_INFO_GET_EXTRA_OBJECT(iic_info_ptr) ((iic_info_ptr)->extra) + +/** + * \brief iic device interface definition + * \details define iic device interface, like iic information structure, + * fuctions to get iic info, open/close/control iic, send/receive data by iic + * \note all this details are implemented by user in user porting code + */ +typedef struct dev_iic { + DEV_IIC_INFO iic_info; /*!< iic device information */ + int32_t (*iic_open) (uint32_t mode, uint32_t param); /*!< open iic device in master/slave mode, \ + when in master mode, param stands for speed mode, \ + when in slave mode, param stands for slave address */ + int32_t (*iic_close) (void); /*!< close iic device */ + int32_t (*iic_control) (uint32_t ctrl_cmd, void *param);/*!< control iic device */ + int32_t (*iic_write) (const void *data, uint32_t len); /*!< send data by iic device (blocking method) */ + int32_t (*iic_read) (void *data, uint32_t len); /*!< read data from iic device (blocking method) */ +} DEV_IIC, * DEV_IIC_PTR; + +/** + * \fn int32_t (* dev_iic::iic_open) (uint32_t mode, uint32_t param) + * \details open an iic device with selected mode (master or slave) with defined \ref param + * \param[in] mode working mode (\ref DEV_MASTER_MODE "master" or \ref DEV_SLAVE_MODE "slave") + * \param[in] param When mode is \ref DEV_MASTER_MODE, param stands for \ref dev_iic_info::speed_mode "speed mode", + * when mode is \ref DEV_SLAVE_MODE, param stands for \ref dev_iic_info::slv_addr "slave device 7bit address" + * \retval E_OK Open successfully without any issues + * \retval E_OPNED If device was opened before with different parameters, + * then just increase the \ref dev_iic_info::opn_cnt "opn_cnt" and return \ref E_OPNED + * \retval E_OBJ Device object is not valid + * \retval E_SYS Device is opened for different mode before, if you want to open it with different mode, you need to fully close it first. + * \retval E_PAR Parameter is not valid + * \retval E_NOSPT Open settings are not supported + */ + +/** + * \fn int32_t (* dev_iic::iic_close) (void) + * \details close an iic device, just decrease the \ref dev_iic_info::opn_cnt "opn_cnt", + * if \ref dev_iic_info::opn_cnt "opn_cnt" equals 0, then close the device + * \retval E_OK Close successfully without any issues(including scenario that device is already closed) + * \retval E_OPNED Device is still opened, the device \ref dev_iic_info::opn_cnt "opn_cnt" decreased by 1 + * \retval E_OBJ Device object is not valid + */ + +/** + * \fn int32_t (* dev_iic::iic_control) (uint32_t ctrl_cmd, void *param) + * \details control an iic device by \ref ctrl_cmd, with passed \ref param. + * you can control iic device using predefined iic control commands defined using \ref DEV_SET_SYSCMD + * (which must be implemented by bsp developer), such as \ref IIC_CMD_SET_SPEED "set iic speed mode", + * \ref IIC_CMD_FLUSH_TX "flush tx" and \ref DEVICE_HAL_IIC_CTRLCMD "more". + * And you can also control iic device using your own specified commands defined using \ref DEV_SET_USRCMD, + * but these specified commands should be defined in your own iic device driver implementation. + * \param[in] ctrl_cmd \ref DEVICE_HAL_IIC_CTRLCMD "control command", to change or get some thing related to iic + * \param[in,out] param parameters that maybe argument of the command, + * or return values of the command, must not be NULL + * \retval E_OK Control device successfully + * \retval E_CLSED Device is not opened + * \retval E_OBJ Device object is not valid or not exists + * \retval E_PAR Parameter is not valid for current control command + * \retval E_SYS Control device failed, due to hardware issues, such as device is disabled + * \retval E_CTX Control device failed, due to different reasons like in transfer state + * \retval E_NOSPT Control command is not supported or not valid + */ + +/** + * \fn int32_t (* dev_iic::iic_write) (const void *data, uint32_t len) + * \details send \ref data through iic with defined \ref len to slave device which slave address is \ref slv_addr. + * \param[in] data pointer to data need to send by iic + * \param[in] len length of data to be sent + * \retval >0 Byte count that was successfully sent for poll method, + * it might can't send that much due to \ref \ref dev_iic_info::err_state "different error state". + * \retval E_OBJ Device object is not valid or not exists + * \retval E_PAR Parameter is not valid + * \retval E_CTX Device is still in transfer state + * \retval E_SYS Can't write data to hardware due to hardware issues, such as device is disabled + */ + +/** + * \fn int32_t (* dev_iic::iic_read) (void *data, uint32_t len) + * \details receive \ref data of defined \ref len through iic from slave device which slave address is \ref slv_addr. + * \param[out] data pointer to data need to received by iic + * \param[in] len length of data to be received + * \retval >0 Byte count that was successfully received for poll method, + * it might can't send that much due to \ref \ref dev_iic_info::err_state "different error state". + * \retval E_OBJ Device object is not valid or not exists + * \retval E_CTX Device is still in transfer state + * \retval E_PAR Parameter is not valid + * \retval E_SYS Can't receive data from hardware due to hardware issues, such as device is disabled + */ +/** @} */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief get an \ref dev_iic "iic device" by iic device id. + * For how to use iic device hal refer to \ref DEVICE_HAL_IIC_DEVSTRUCT "Functions in iic device structure" + * \param[in] iic_id id of iic, defined by user + * \retval !NULL pointer to an \ref dev_iic "iic device structure" + * \retval NULL failed to find the iic device by \ref iic_id + * \note need to implemented by user in user code + */ +extern DEV_IIC_PTR iic_get_dev(int32_t iic_id); + +#ifdef __cplusplus +} +#endif + +/** @} */ +#endif /* _DEVICE_HAL_IIC_H_ */ diff --git a/hw/mcu/arc/src/ext/sdk/device/device_hal/inc/dev_spi.h b/hw/mcu/arc/src/ext/sdk/device/device_hal/inc/dev_spi.h new file mode 100644 index 000000000..4469654e5 --- /dev/null +++ b/hw/mcu/arc/src/ext/sdk/device/device_hal/inc/dev_spi.h @@ -0,0 +1,577 @@ +/* ------------------------------------------ + * Copyright (c) 2017, Synopsys, Inc. All rights reserved. + + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + + * 1) Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + + * 2) 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. + + * 3) Neither the name of the Synopsys, Inc., nor the names of its contributors may + * be used to endorse or promote products derived from this software without + * specific prior written permission. + + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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. + * + * \version 2017.03 + * \date 2014-06-16 + * \author Huaqi Fang(Huaqi.Fang@synopsys.com) +--------------------------------------------- */ + +/** + * \defgroup DEVICE_HAL_SPI SPI Device HAL Interface + * \ingroup DEVICE_HAL_DEF + * \brief definitions for spi device hardware layer (\ref dev_spi.h) + * \details provide interfaces for spi driver to implement + * Here is a diagram for the spi interface. + * + * \htmlonly + *
+ *
+ * SPI Device HAL Interface Diagram + *

SPI Device HAL Interface Diagram

+ *
+ *
+ * \endhtmlonly + * + * @{ + * + * \file + * \brief spi device hardware layer definitions + * \details provide common definitions for spi device, + * then software developer can develop spi driver + * following this definitions, and the applications + * can directly call this definition to realize functions + */ + +#ifndef _DEVICE_HAL_SPI_H_ +#define _DEVICE_HAL_SPI_H_ + +#include "device/device_hal/inc/dev_common.h" + + +/** + * \defgroup DEVICE_HAL_SPI_CTRLCMD SPI Device Control Commands + * \ingroup DEVICE_HAL_SPI + * \brief Definitions for spi control command, used in \ref dev_spi::spi_control "SPI IO Control" + * \details These commands defined here can be used in user code directly. + * - Parameters Usage + * - For passing parameters like integer, just use uint32_t/int32_t to directly pass values + * - For passing parameters for a structure, please use pointer to pass values + * - For getting some data, please use pointer to store the return data + * - Common Return Values + * - \ref E_OK, Control device successfully + * - \ref E_CLSED, Device is not opened + * - \ref E_OBJ, Device object is not valid or not exists + * - \ref E_PAR, Parameter is not valid for current control command + * - \ref E_SYS, Control device failed, due to hardware issues such as device is disabled + * - \ref E_CTX, Control device failed, due to different reasons like in transfer state + * - \ref E_NOSPT, Control command is not supported or not valid + * - Usage Comment + * - For SPI poll or interrupt read/write/transfer operations, only 1 operation can be triggered. + * If there is a operation is running, any other operation will return \ref E_CTX + * - If SPI is in transfer, then the following operations may return \ref E_CTX. Like + * \ref SPI_CMD_SET_CLK_MODE, \ref SPI_CMD_SET_TXINT_BUF, \ref SPI_CMD_SET_RXINT_BUF, + * \ref SPI_CMD_SET_TXINT, \ref SPI_CMD_SET_RXINT, \ref SPI_CMD_ABORT_TX, \ref SPI_CMD_ABORT_RX, + * \ref SPI_CMD_FLUSH_TX, \ref SPI_CMD_FLUSH_RX, \ref SPI_CMD_SET_DFS, \ref SPI_CMD_TRANSFER_POLLING, + * \ref SPI_CMD_TRANSFER_INT, \ref SPI_CMD_ABORT_XFER, \ref SPI_CMD_MST_SEL_DEV, \ref SPI_CMD_MST_DSEL_DEV, + * \ref SPI_CMD_MST_SET_FREQ and \ref dev_spi::spi_write "SPI Poll Write" or \ref dev_spi::spi_read "SPI Poll Read". + * @{ + */ + +/** Define SPI control commands for common usage */ +#define DEV_SET_SPI_SYSCMD(cmd) DEV_SET_SYSCMD((cmd)) +/** Define SPI control commands for master usage */ +#define DEV_SET_SPI_MST_SYSCMD(cmd) DEV_SET_SYSCMD(0x00001000|(cmd)) +/** Define SPI control commands for slave usage */ +#define DEV_SET_SPI_SLV_SYSCMD(cmd) DEV_SET_SYSCMD(0x00002000|(cmd)) + + +/* ++++ Common commands for SPI Device ++++ */ +/** + * Get \ref dev_spi_info::status "current device status" + * - Param type : uint32_t * + * - Param usage : store result of current status + * - Return value explanation : + */ +#define SPI_CMD_GET_STATUS DEV_SET_SPI_SYSCMD(0) +/** + * set the \ref dev_spi_info::clk_mode "clock mode" of spi transfer + * - Param type : uint32_t + * - Param usage : spi clock mode to choose clock phase and clock polarity + * - Return value explanation : + */ +#define SPI_CMD_SET_CLK_MODE DEV_SET_SPI_SYSCMD(1) +/** + * set spi \ref dev_spi_info::dfs "data frame size" + * - Param type : uint32_t + * - Param usage : should > 0 + * - Return value explanation : If dfs is not supported, then return \ref E_SYS + */ +#define SPI_CMD_SET_DFS DEV_SET_SPI_SYSCMD(2) +/** + * set the \ref dev_spi_info::dummy "dummy data" during spi transfer + * - Param type : uint32_t + * - Param usage : dummy data to transfer + * - Return value explanation : + */ +#define SPI_CMD_SET_DUMMY_DATA DEV_SET_SPI_SYSCMD(3) +/** + * Set \ref dev_spi_cbs::tx_cb "spi transmit success callback" function + * when all required bytes are transmitted for interrupt method + * - Param type : \ref DEV_CALLBACK * or NULL + * - Param usage : transmit success callback function for spi + * - Return value explanation : + */ +#define SPI_CMD_SET_TXCB DEV_SET_SPI_SYSCMD(4) +/** + * Set \ref dev_spi_cbs::rx_cb "spi receive success callback" function + * when all required bytes are received for interrupt method + * - Param type : \ref DEV_CALLBACK * or NULL + * - Param usage : receive success callback function for spi + * - Return value explanation : + */ +#define SPI_CMD_SET_RXCB DEV_SET_SPI_SYSCMD(5) +/** + * Set \ref dev_spi_cbs::xfer_cb "spi transfer success callback" function + * when all required transfer are done for interrupt method + * - Param type : \ref DEV_CALLBACK * or NULL + * - Param usage : transfer success callback function for spi + * - Return value explanation : + */ +#define SPI_CMD_SET_XFERCB DEV_SET_SPI_SYSCMD(6) +/** + * Set \ref dev_spi_cbs::err_cb "spi transfer error callback" function + * when something error happened for interrupt method + * - Param type : \ref DEV_CALLBACK * or NULL + * - Param usage : transfer error callback function for spi + * - Return value explanation : + */ +#define SPI_CMD_SET_ERRCB DEV_SET_SPI_SYSCMD(7) +/** + * Set buffer in interrupt transmit, and it will set \ref dev_spi_info::xfer "spi tranfer". + * - SPI master and slave mode use case \n + * For both master and slave mode, if you set tx buffer to NULL, when tx interrupt is enabled and entered into tx interrupt, + * it will automatically disable the tx interrupt, so when you want to transfer something, you need to set the + * tx buffer to Non-NULL and enable tx interrupt, when the tx buffer is sent, it will disable the tx interrupt + * and call tx callback function if available. + * - Param type : DEV_BUFFER * or NULL + * - Param usage : buffer structure pointer, if param is NULL, then it will set xfer to empty + * - Return value explanation : + */ +#define SPI_CMD_SET_TXINT_BUF DEV_SET_SPI_SYSCMD(8) +/** + * Set buffer in interrupt receive, and it will set \ref dev_spi_info::xfer "spi tranfer". + * - SPI master mode use case \n + * Similar to \ref SPI_CMD_SET_TXINT_BUF + * - SPI slave mode use case \n + * Similiar to \ref SPI_CMD_SET_TXINT_BUF + * - Param type : DEV_BUFFER * or NULL + * - Param usage : buffer structure pointer, if param is NULL, then it will set xfer to empty + * - Return value explanation : + */ +#define SPI_CMD_SET_RXINT_BUF DEV_SET_SPI_SYSCMD(9) +/** + * Enable or disable transmit interrupt, + * for master mode, only one of tx and rx interrupt can be enabled, + * if tx interrupt is enabled, then rx interrupt can't be enabled. + * - Param type : uint32_t + * - Param usage : enable(none-zero) or disable(zero) flag + * - Return value explanation : + */ +#define SPI_CMD_SET_TXINT DEV_SET_SPI_SYSCMD(10) +/** + * Enable or disable receive interrupt, + * for master mode, only one of tx and rx interrupt can be enabled, + * if rx interrupt is enabled, then tx interrupt can't be enabled. + * - Param type : uint32_t + * - Param usage : enable(none-zero) or disable(zero) flag + * - Return value explanation : + */ +#define SPI_CMD_SET_RXINT DEV_SET_SPI_SYSCMD(11) +/** + * start the transfer by polling + * - Param type : \ref DEV_SPI_TRANSFER * + * - Param usage : + * - Return value explanation : + */ +#define SPI_CMD_TRANSFER_POLLING DEV_SET_SPI_SYSCMD(12) +/** + * start the transfer by interrupt + * - Param type : \ref DEV_SPI_TRANSFER * or NULL + * - Param usage : If NULL, it will disable transfer interrupt, if not NULL, it will enable transfer interrupt + * - Return value explanation : + */ +#define SPI_CMD_TRANSFER_INT DEV_SET_SPI_SYSCMD(13) +/** + * Abort current interrupt transmit operation if tx interrupt enabled, + * it will disable transmit interrupt, and set \ref DEV_IN_TX_ABRT + * in \ref dev_spi_info::status "status" variable, + * and call the transmit callback function, when tx callback is finished, + * it will clear \ref DEV_IN_TX_ABRT and return + * - Param type : NULL + * - Param usage : + * - Return value explanation : + */ +#define SPI_CMD_ABORT_TX DEV_SET_SPI_SYSCMD(14) +/** + * Abort current interrupt receive operation if rx interrupt enabled, + * it will disable receive interrupt, and set \ref DEV_IN_TX_ABRT + * in \ref dev_spi_info::status "status" variable, + * and call the receive callback function, when rx callback is finished, + * it will clear \ref DEV_IN_TX_ABRT and return + * - Param type : NULL + * - Param usage : + * - Return value explanation : + */ +#define SPI_CMD_ABORT_RX DEV_SET_SPI_SYSCMD(15) +/** + * Abort current interrupt transfer operation if transfer is issued, + * it will disable transfer interrupt, and set \ref DEV_IN_XFER_ABRT + * in \ref dev_spi_info::status "status" variable, + * and call the transfer callback function, when xfer callback is finished, + * it will clear \ref DEV_IN_XFER_ABRT and return + * - Param type : NULL + * - Param usage : + * - Return value explanation : + */ +#define SPI_CMD_ABORT_XFER DEV_SET_SPI_SYSCMD(16) +/** + * Do a software reset for SPI device, it will stop current transfer, + * and clear error state and bring device to normal state, set next condition to STOP + * - Param type : NULL + * - Param usage : + * - Return value explanation : + */ +#define SPI_CMD_RESET DEV_SET_SPI_SYSCMD(17) +/** + * Flush spi tx fifo, this will clear the data in tx fifo + * - Param type : NULL + * - Param usage : + * - Return value explanation : + */ +#define SPI_CMD_FLUSH_TX DEV_SET_SPI_SYSCMD(18) +/** + * Flush spi rx fifo, this will clear the data in rx fifo + * - Param type : NULL + * - Param usage : + * - Return value explanation : + */ +#define SPI_CMD_FLUSH_RX DEV_SET_SPI_SYSCMD(19) +/** + * Enable spi device + * - Param type : NULL + * - Param usage : param is not required + * - Return value explanation : + */ +#define SPI_CMD_ENA_DEV DEV_SET_SPI_SYSCMD(20) +/** + * Disable spi device, when device is disabled, + * only \ref SPI_CMD_ENA_DEV, \ref SPI_CMD_DIS_DEV, + * \ref SPI_CMD_GET_STATUS and \ref SPI_CMD_RESET + * commands can be executed, other commands will return \ref E_SYS + * - Param type : NULL + * - Param usage : param is not required + * - Return value explanation : + */ +#define SPI_CMD_DIS_DEV DEV_SET_SPI_SYSCMD(21) +/** + * Get how many bytes space in spi are available to transmit, + * this can be used in interrupt callback functions, + * cooperate with \ref dev_spi::spi_write "spi_write" API to realize non-blocked write + * - Param type : int32_t * + * - Param usage : store the write available bytes, > 0 for available bytes, 0 for not available + * - Return value explanation : + */ +#define SPI_CMD_GET_TXAVAIL DEV_SET_SPI_SYSCMD(22) +/** + * Get how many bytes in spi are available to receive, + * this can be used in interrupt callback functions, + * cooperate with \ref dev_spi::spi_read "spi_read" API to realize non-blocked read + * - Param type : int32_t * + * - Param usage : store the read available bytes, > 0 for available bytes, 0 for not available + * - Return value explanation : + */ +#define SPI_CMD_GET_RXAVAIL DEV_SET_SPI_SYSCMD(23) + + +/* ++++ Master only commands for SPI Device ++++ */ +/** + * select spi slave device + * - Param type : uint32_t + * - Param usage : the number of spi slave device to select + * - Return value explanation : return \ref E_SYS when selection can't be done, return \ref E_CTX during transfer + */ +#define SPI_CMD_MST_SEL_DEV DEV_SET_SPI_MST_SYSCMD(0) +/** + * de-select spi slave device + * - Param type : uint32_t + * - Param usage : the number of spi slave device to de-select + * - Return value explanation : return \ref E_SYS when selection can't be done, return \ref E_CTX during transfer + */ +#define SPI_CMD_MST_DSEL_DEV DEV_SET_SPI_MST_SYSCMD(1) + /** + * Set \ref dev_spi_info::freq "spi frequency". + * - Param type : uint32_t + * - Param usage : spi freq + * - Return value explanation : no return + */ +#define SPI_CMD_MST_SET_FREQ DEV_SET_SPI_MST_SYSCMD(2) + + +/* ++++ Slave only commands for SPI Device ++++ */ + +/* \todo add spi slave related CMDs */ + +/** @} */ + +/** + * \defgroup DEVICE_HAL_SPI_CALLBACK SPI Interrupt callback functions + * \ingroup DEVICE_HAL_SPI + * \brief callback function structure for SPI device + * @{ + */ +typedef struct dev_spi_cbs { + DEV_CALLBACK tx_cb; /*!< spi data transmit success required bytes callback */ + DEV_CALLBACK rx_cb; /*!< spi data receive success required bytes callback */ + DEV_CALLBACK err_cb; /*!< spi error callback */ + DEV_CALLBACK xfer_cb; /*!< transfer callback */ +} DEV_SPI_CBS, *DEV_SPI_CBS_PTR; +/** @} */ + +/** SPI Clock Mode */ +typedef enum spi_clk_mode { + SPI_CPOL_0_CPHA_0 = 0, /*!< Inactive state of serial clock is low, serial clock toggles in middle of first data bit */ + SPI_CPOL_0_CPHA_1 = 1, /*!< Inactive state of serial clock is low, serial clock toggles at start of first data bit */ + SPI_CPOL_1_CPHA_0 = 2, /*!< Inactive state of serial clock is high, serial clock toggles in middle of first data bit */ + SPI_CPOL_1_CPHA_1 = 3, /*!< Inactive state of serial clock is high, serial clock toggles at start of first data bit */ + + SPI_CLK_MODE_0 = SPI_CPOL_0_CPHA_0, /*!< Equal to \ref SPI_CPOL_0_CPHA_0 */ + SPI_CLK_MODE_1 = SPI_CPOL_0_CPHA_1, /*!< Equal to \ref SPI_CPOL_0_CPHA_1 */ + SPI_CLK_MODE_2 = SPI_CPOL_1_CPHA_0, /*!< Equal to \ref SPI_CPOL_1_CPHA_0 */ + SPI_CLK_MODE_3 = SPI_CPOL_1_CPHA_1 /*!< Equal to \ref SPI_CPOL_1_CPHA_1 */ +} SPI_CLK_MODE; + +#define SPI_CLK_MODE_DEFAULT SPI_CPOL_0_CPHA_0 /*!< Default SPI device clock mode */ + +/** + * \defgroup DEVICE_HAL_SPI_DEVSTRUCT SPI Device Structure + * \ingroup DEVICE_HAL_SPI + * \brief contains definitions of spi device structure. + * \details this structure will be used in user implemented code, which was called + * Device Driver Implement Layer for spi to realize in user code. + * @{ + */ +typedef struct dev_spi_transfer DEV_SPI_TRANSFER, *DEV_SPI_TRANSFER_PTR; +/** + * \brief spi read and write data structure used by \ref SPI_CMD_TRANSFER + * spi write then read data + * + */ +struct dev_spi_transfer { + DEV_SPI_TRANSFER *next; + /* Calc by software */ + /** tot_len = (tx_totlen>rx_totlen)?tx_totlen:rx_totlen */ + uint32_t tot_len; + /* Set by user */ + uint8_t *tx_buf; + uint32_t tx_ofs; + uint32_t tx_len; + uint8_t *rx_buf; + uint32_t rx_ofs; + uint32_t rx_len; + /* Should auto set to proper value during set buffer value */ + uint32_t tx_idx; + uint32_t tx_totlen; /** tx_totlen = tx_len + tx_ofs */ + uint32_t rx_idx; + uint32_t rx_totlen; /** rx_totlen = rx_len + rx_ofs */ +}; + +/** Set tx buffer of device spi transfer */ +#define DEV_SPI_XFER_SET_TXBUF(xfer, buf, ofs, len) { \ + (xfer)->tx_buf = (uint8_t *)(buf); \ + (xfer)->tx_len = (uint32_t)(len); \ + (xfer)->tx_ofs = (uint32_t)(ofs); \ + (xfer)->tx_idx = 0; \ + (xfer)->tx_totlen = ( (uint32_t)(len) \ + + (uint32_t)(ofs) ) ; \ + } + +/** Set rx buffer of device spi transfer */ +#define DEV_SPI_XFER_SET_RXBUF(xfer, buf, ofs, len) { \ + (xfer)->rx_buf = (uint8_t *)(buf); \ + (xfer)->rx_len = (uint32_t)(len); \ + (xfer)->rx_ofs = (uint32_t)(ofs); \ + (xfer)->rx_idx = 0; \ + (xfer)->rx_totlen = ( (uint32_t)(len) \ + + (uint32_t)(ofs) ) ; \ + } + +/** Calculate total length of current transfer without next transfer */ +#define DEV_SPI_XFER_CALC_TOTLEN(xfer) (xfer)->tot_len = \ + ((xfer)->tx_totlen > (xfer)->rx_totlen) ? (xfer)->tx_totlen : (xfer)->rx_totlen ; + +/** Set next SPI transfer */ +#define DEV_SPI_XFER_SET_NEXT(xfer, next_xfer) (xfer)->next = (next_xfer); + +/** Init spi transfer */ +#define DEV_SPI_XFER_INIT(xfer) { \ + (xfer)->tx_idx = 0; \ + (xfer)->rx_idx = 0; \ + (xfer)->tx_totlen = ((xfer)->tx_len \ + + (xfer)->tx_ofs) ; \ + (xfer)->rx_totlen = ((xfer)->rx_len \ + + (xfer)->rx_ofs) ; \ + DEV_SPI_XFER_CALC_TOTLEN(xfer); \ + } +/** + * \brief spi information struct definition + * \details informations about spi open state, working state, + * frequency, spi registers, working method, interrupt number + */ +typedef struct dev_spi_info { + void *spi_ctrl; /*!< spi control related */ + uint32_t status; /*!< current working status, refer to \ref DEVICE_HAL_COMMON_DEVSTATUS, this should be \ref DEV_ENABLED for first open */ + uint32_t freq; /*!< spi working baudrate */ + uint8_t mode; /*!< spi working mode (master/slave) */ + uint8_t clk_mode; /*!< spi clock phase and polarity, this should be \ref SPI_CLK_MODE_DEFAULT for first open */ + uint8_t opn_cnt; /*!< spi open count, open it will increase 1, close it will decrease 1, 0 for close, >0 for open */ + uint8_t slave; /*!< current selected slave device no, start from 0, this should be \ref SPI_SLAVE_NOT_SELECTED for first open */ + uint8_t dfs; /*!< data frame size, this should be \ref SPI_DFS_DEFAULT for first open */ + + DEV_SPI_TRANSFER xfer; /*!< spi transfer, this should be set to all zero for first open */ + DEV_SPI_CBS spi_cbs; /*!< spi callbacks, for both master and slave mode, this should be all NULL for first open */ + void *extra; /*!< a extra pointer to get hook to applications which should not used by bsp developer, + this should be NULL for first open and you can \ref DEV_SPI_INFO_SET_EXTRA_OBJECT "set" + or \ref DEV_SPI_INFO_GET_EXTRA_OBJECT "get" the extra information pointer */ + uint32_t dummy; /*!< dummy write data when send and receive, this should be \ref SPI_DUMMY_DEFAULT for first open */ +} DEV_SPI_INFO, * DEV_SPI_INFO_PTR; + +/** Set extra information pointer of spi info */ +#define DEV_SPI_INFO_SET_EXTRA_OBJECT(spi_info_ptr, extra_info) (spi_info_ptr)->extra = (void *)(extra_info) +/** Get extra information pointer of spi info */ +#define DEV_SPI_INFO_GET_EXTRA_OBJECT(spi_info_ptr) ((spi_info_ptr)->extra) + +#define SPI_DFS_DEFAULT 8 /*!< Default spi data frame size */ +#define SPI_SLAVE_NOT_SELECTED (0xFF) /*!< Slave is not selected */ +#define SPI_DUMMY_DEFAULT (0xFF) /*!< default dummy value for first open */ + +/** + * \brief spi device interface definition + * \details define spi device interface, like spi information structure, + * fuctions to get spi info, open/close/control spi, send/receive data by spi + * \note all this details are implemented by user in user porting code + */ +typedef struct dev_spi { + DEV_SPI_INFO spi_info; /*!< spi device information */ + int32_t (*spi_open) (uint32_t mode, uint32_t param); /*!< open spi device in master/slave mode, \ + when in master mode, param stands for frequency, \ + when in slave mode, param stands for clock mode */ + int32_t (*spi_close) (void); /*!< close spi device */ + int32_t (*spi_control) (uint32_t ctrl_cmd, void *param); /*!< control spi device */ + int32_t (*spi_write) (const void *data, uint32_t len); /*!< send data to spi device (blocking method) */ + int32_t (*spi_read) (void *data, uint32_t len); /*!< read data from spi device (blocking method) */ +} DEV_SPI, * DEV_SPI_PTR; + +/** + * \fn int32_t (* dev_spi::spi_open) (uint32_t mode, uint32_t param) + * \details open an spi device with selected mode (master or slave) with defined \ref param + * \param[in] mode working mode (\ref DEV_MASTER_MODE "master" or \ref DEV_SLAVE_MODE "slave") + * \param[in] param When mode is \ref DEV_MASTER_MODE, param stands for \ref dev_spi_info::freq "frequency", + * when mode is \ref DEV_SLAVE_MODE, param stands for \ref dev_spi_info::clk_mode "slave clock mode" + * \retval E_OK Open successfully without any issues + * \retval E_OPNED If device was opened before with different parameters, + * then just increase the \ref dev_spi_info::opn_cnt "opn_cnt" and return \ref E_OPNED + * \retval E_OBJ Device object is not valid + * \retval E_SYS Device is opened for different mode before, if you want to open it with different mode, you need to fully close it first. + * \retval E_PAR Parameter is not valid + * \retval E_NOSPT Open settings are not supported + */ + +/** + * \fn int32_t (* dev_spi::spi_close) (void) + * \details close an spi device, just decrease the \ref dev_spi_info::opn_cnt "opn_cnt", + * if \ref dev_spi_info::opn_cnt "opn_cnt" equals 0, then close the device + * \retval E_OK Close successfully without any issues(including scenario that device is already closed) + * \retval E_OPNED Device is still opened, the device \ref dev_spi_info::opn_cnt "opn_cnt" decreased by 1 + * \retval E_OBJ Device object is not valid + */ + +/** + * \fn int32_t (* dev_spi::spi_control) (uint32_t ctrl_cmd, void *param) + * \details control an spi device by \ref ctrl_cmd, with passed \ref param. + * you can control spi device using predefined spi control commands defined using \ref DEV_SET_SYSCMD + * (which must be implemented by bsp developer), such as \ref SPI_CMD_MST_SET_FREQ "set spi master frequency", + * \ref SPI_CMD_FLUSH_TX "flush tx" and \ref DEVICE_HAL_SPI_CTRLCMD "more". + * And you can also control spi device using your own specified commands defined using \ref DEV_SET_USRCMD, + * but these specified commands should be defined in your own spi device driver implementation. + * \param[in] ctrl_cmd \ref DEVICE_HAL_SPI_CTRLCMD "control command", to change or get some thing related to spi + * \param[in,out] param parameters that maybe argument of the command, + * or return values of the command, must not be NULL + * \retval E_OK Control device successfully + * \retval E_CLSED Device is not opened + * \retval E_OBJ Device object is not valid or not exists + * \retval E_PAR Parameter is not valid for current control command + * \retval E_SYS Control device failed, due to hardware issues, such as device is disabled + * \retval E_CTX Control device failed, due to different reasons like in transfer state + * \retval E_NOSPT Control command is not supported or not valid + */ + +/** + * \fn int32_t (* dev_spi::spi_write) (const void *data, uint32_t len) + * \details send \ref data through spi with defined \ref len to slave device . + * \param[in] data pointer to data need to send by spi + * \param[in] len length of data to be sent + * \retval >0 Byte count that was successfully sent for poll method + * \retval E_OBJ Device object is not valid or not exists + * \retval E_PAR Parameter is not valid + * \retval E_CTX Device is still in transfer state + * \retval E_SYS Can't write data to hardware due to hardware issues, such as device is disabled + */ + +/** + * \fn int32_t (* dev_spi::spi_read) (void *data, uint32_t len) + * \details receive \ref data of defined \ref len through spi from slave device . + * \param[out] data pointer to data need to received by spi + * \param[in] len length of data to be received + * \retval >0 Byte count that was successfully received for poll method + * \retval E_OBJ Device object is not valid or not exists + * \retval E_CTX Device is still in transfer state + * \retval E_PAR Parameter is not valid + * \retval E_SYS Can't receive data from hardware due to hardware issues, such as device is disabled + */ +/** @} */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief get an \ref dev_spi "spi device" by spi device id. + * For how to use spi device hal refer to \ref dev_spi "Functions in spi device structure" + * \param[in] spi_id id of spi, defined by user + * \retval !NULL pointer to an \ref dev_spi "spi device structure" + * \retval NULL failed to find the spi device by \ref spi_id + * \note need to implemented by user in user code + */ +extern DEV_SPI_PTR spi_get_dev(int32_t spi_id); + +#ifdef __cplusplus +} +#endif + +/** @} */ +#endif /* _DEVICE_HAL_SPI_H_ */ diff --git a/hw/mcu/arc/src/ext/sdk/device/device_hal/inc/dev_uart.h b/hw/mcu/arc/src/ext/sdk/device/device_hal/inc/dev_uart.h new file mode 100644 index 000000000..c8e17d642 --- /dev/null +++ b/hw/mcu/arc/src/ext/sdk/device/device_hal/inc/dev_uart.h @@ -0,0 +1,475 @@ +/* ------------------------------------------ + * Copyright (c) 2016, Synopsys, Inc. All rights reserved. + + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + + * 1) Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + + * 2) 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. + + * 3) Neither the name of the Synopsys, Inc., nor the names of its contributors may + * be used to endorse or promote products derived from this software without + * specific prior written permission. + + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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. + * + * \version 2016.05 + * \date 2014-06-16 + * \author Huaqi Fang(Huaqi.Fang@synopsys.com) +--------------------------------------------- */ + +/** + * \defgroup DEVICE_HAL_UART UART Device HAL Interface + * \ingroup DEVICE_HAL_DEF + * \brief Definitions for uart device hardware layer (\ref dev_uart.h) + * \details Provide unified APIs for uart driver to implement. + * Here is a diagram for the uart interface. + * + * \htmlonly + *
+ *
+ * UART Device HAL Interface Diagram + *

UART Device HAL Interface Diagram

+ *
+ *
+ * \endhtmlonly + * + * ### Reference Links + * * [Serial Port](https://en.wikipedia.org/wiki/Serial_port) + * + * @{6 + * + * \file + * \brief uart device hardware layer definitions + * \details Provide common definitions for uart device, + * then software developer can develop uart driver + * following this definitions, and the applications + * can directly call this definition to realize functions + * + */ + +#ifndef _DEVICE_HAL_UART_H_ +#define _DEVICE_HAL_UART_H_ + +#include "device/device_hal/inc/dev_common.h" + +/** + * \defgroup DEVICE_HAL_UART_BAUD UART Device Baudrate Definitions + * \ingroup DEVICE_HAL_UART + * \brief Macros for uart baudrate. + * \details Definitions for baudrate from 4800 to 115200bps. + * @{ + */ +/* + * defines for uart baudrates + */ +#define UART_BAUDRATE_110 (110) /*!< uart baudrate 110bps */ +#define UART_BAUDRATE_300 (300) /*!< uart baudrate 300bps */ +#define UART_BAUDRATE_600 (600) /*!< uart baudrate 600bps */ +#define UART_BAUDRATE_1200 (1200) /*!< uart baudrate 1200bps */ +#define UART_BAUDRATE_2400 (2400) /*!< uart baudrate 2400bps */ +#define UART_BAUDRATE_4800 (4800) /*!< uart baudrate 4800bps */ +#define UART_BAUDRATE_9600 (9600) /*!< uart baudrate 9600bps */ +#define UART_BAUDRATE_14400 (14400) /*!< uart baudrate 14400bps */ +#define UART_BAUDRATE_19200 (19200) /*!< uart baudrate 19200bps */ +#define UART_BAUDRATE_38400 (38400) /*!< uart baudrate 38400bps */ +#define UART_BAUDRATE_57600 (57600) /*!< uart baudrate 57600bps */ +#define UART_BAUDRATE_115200 (115200) /*!< uart baudrate 115200bps */ +#define UART_BAUDRATE_230400 (230400) /*!< uart baudrate 230400bps */ +#define UART_BAUDRATE_460800 (460800) /*!< uart baudrate 460800bps */ +#define UART_BAUDRATE_921600 (921600) /*!< uart baudrate 921600bps */ +/** @} */ + +/** + * \defgroup DEVICE_HAL_UART_FORMAT UART Device Format Definitions + * \ingroup DEVICE_HAL_UART + * \brief Macros for uart format. + * \details Definitions for uart format like databits, parity, stopbits. + * @{ + */ +/** + * UART Device Parity Types Enum + */ +typedef enum { + UART_PARITY_NONE = 0, /*!< no parity bit */ + UART_PARITY_ODD = 1, /*!< odd parity bit */ + UART_PARITY_EVEN = 2, /*!< even parity bit */ + UART_PARITY_MARK = 3, /*!< mark parity bit, always logical 1 */ + UART_PARITY_SPACE = 4 /*!< space parity bit, always logical 0 */ +} UART_PARITY; + +/** + * UART Device Stop Bits Enum + */ +typedef enum { + UART_STPBITS_ONE = 0, /*!< 1 stop bit */ + UART_STPBITS_ONEHALF = 1, /*!< 1.5 stop bits */ + UART_STPBITS_TWO = 2 /*!< 2 stop bits */ +} UART_STOPBITS; + +/** + * UART DPS Format: databits/parity/stopbits + */ +typedef struct uart_dps_format { + uint32_t databits; /*!< data bits */ + UART_PARITY parity; /*!< parity bit type */ + UART_STOPBITS stopbits; /*!< stop bits */ +} UART_DPS_FORMAT; + +#define UART_DATABITS_DEFAULT 8 /*!< default data bits */ + +/** Default UART DPS format */ +static const UART_DPS_FORMAT dps_format_default = {UART_DATABITS_DEFAULT, UART_PARITY_NONE, UART_STPBITS_ONE}; +/** @} */ + +/** + * UART Device Hardware Flow Control Types Enum + */ +typedef enum { + UART_FC_NONE = 0, /*!< Non hardware flow control */ + UART_FC_RTS = 1, /*!< Request To Send */ + UART_FC_CTS = 2, /*!< Clear To Send */ + UART_FC_BOTH = 3 /*!< Both hardware flow control methods */ +} UART_HW_FLOW_CONTROL; +/** Default hardware flow control method */ +static const UART_HW_FLOW_CONTROL hwfc_default = UART_FC_NONE; + +/** + * \defgroup DEVICE_HAL_UART_CTRLCMD UART Device Control Commands + * \ingroup DEVICE_HAL_UART + * \brief Definitions for uart control command, used in \ref dev_uart::uart_control "UART IO Control" + * \details These commands defined here can be used in user code directly. + * - Parameters Usage + * - For passing parameters like integer, just use uint32_t/int32_t to directly pass values + * - For passing parameters for a structure, please use pointer to pass values + * - For getting some data, please use pointer to store the return data + * - Common Return Values + * - \ref E_OK, Control device successfully + * - \ref E_CLSED, Device is not opened + * - \ref E_OBJ, Device object is not valid or not exists + * - \ref E_PAR, Parameter is not valid for current control command + * - \ref E_SYS, Control device failed, due to hardware issues such as device is disabled + * - \ref E_CTX, Control device failed, due to different reasons like in transfer state + * - \ref E_NOSPT, Control command is not supported or not valid + * @{ + */ +/** + * Set \ref dev_uart_info::baudrate "uart baudrate". + * - Param type : uint32_t + * - Param usage : uart baudrate, must above zero. Here is a list of \ref DEVICE_HAL_UART_BAUD "possible baudrates" + * - Return value explanation : + */ +#define UART_CMD_SET_BAUD DEV_SET_SYSCMD(0) +/** + * Get \ref dev_uart_info::status "current device status" + * - Param type : uint32_t * + * - Param usage : store result of current status + * - Return value explanation : + */ +#define UART_CMD_GET_STATUS DEV_SET_SYSCMD(1) +/** + * Enable uart device + * - Param type : NULL + * - Param usage : param is not required + * - Return value explanation : + */ +#define UART_CMD_ENA_DEV DEV_SET_SYSCMD(2) +/** + * Disable uart device, when device is disabled, + * only \ref UART_CMD_ENA_DEV, \ref UART_CMD_DIS_DEV and + * \ref UART_CMD_GET_STATUS commands can be executed, + * other commands will return \ref E_SYS + * - Param type : NULL + * - Param usage : param is not required + * - Return value explanation : + */ +#define UART_CMD_DIS_DEV DEV_SET_SYSCMD(3) +/** + * Flush uart device output + * - Param type : NULL + * - Param usage : param is not required + * - Return value explanation : + */ +#define UART_CMD_FLUSH_OUTPUT DEV_SET_SYSCMD(4) +/** + * Get how many bytes space in uart are available to transmit, + * this can be used in interrupt callback functions, + * cooperate with \ref dev_uart::uart_write "uart_write" API to realize non-blocked write + * - Param type : int32_t * + * - Param usage : store the write available bytes, > 0 for available bytes, 0 for not available + * - Return value explanation : + */ +#define UART_CMD_GET_TXAVAIL DEV_SET_SYSCMD(5) +/** + * Get how many bytes in uart are available to receive, + * this can be used in interrupt callback functions, + * cooperate with \ref dev_uart::uart_read "uart_read" API to realize non-blocked read + * - Param type : int32_t * + * - Param usage : store the read available bytes, > 0 for available bytes, 0 for not available + * - Return value explanation : + */ +#define UART_CMD_GET_RXAVAIL DEV_SET_SYSCMD(6) +/** + * Cause a break condition to be transmitted to the receiving device + * - Param type : NULL + * - Param usage : param is not required + * - Return value explanation : + */ +#define UART_CMD_BREAK_SET DEV_SET_SYSCMD(7) +/** + * Clear break condition and return to normal + * - Param type : NULL + * - Param usage : param is not required + * - Return value explanation : + */ +#define UART_CMD_BREAK_CLR DEV_SET_SYSCMD(8) +/** + * Change uart \ref dev_uart_info::dps_format "D/P/S(Data/Parity/Stop) format" + * - Param type : \ref UART_DPS_FORMAT * + * - Param usage : uart dps format including databits, parity and stopbits + * - Return value explanation : + */ +#define UART_CMD_SET_DPS_FORMAT DEV_SET_SYSCMD(9) +/** + * Set uart device \ref dev_uart_info::hwfc "hardware flow control" + * - Param type : \ref UART_HW_FLOW_CONTROL + * - Param usage : uart dps format including databits, parity and stopbits + * - Return value explanation : + */ +#define UART_CMD_SET_HWFC DEV_SET_SYSCMD(10) +/** + * Set \ref dev_uart_cbs::tx_cb "uart transmit success callback" function + * when all required bytes are transmitted for interrupt method + * - Param type : \ref DEV_CALLBACK * or NULL + * - Param usage : transmit success callback function for uart + * - Return value explanation : + */ +#define UART_CMD_SET_TXCB DEV_SET_SYSCMD(11) +/** + * Set \ref dev_uart_cbs::rx_cb "uart receive success callback" function + * when all required bytes are received for interrupt method + * - Param type : \ref DEV_CALLBACK * or NULL + * - Param usage : receive success callback function for uart + * - Return value explanation : + */ +#define UART_CMD_SET_RXCB DEV_SET_SYSCMD(12) +/** + * Set \ref dev_uart_cbs::err_cb "uart transfer error callback" function + * when something error happened for interrupt method + * - Param type : \ref DEV_CALLBACK * or NULL + * - Param usage : transfer error callback function for uart + * - Return value explanation : + */ +#define UART_CMD_SET_ERRCB DEV_SET_SYSCMD(13) +/** + * Set transmit buffer via interrupt, and it will set \ref dev_uart_info::tx_buf "tx_buf" + * - Param type : DEV_BUFFER * or NULL + * - Param usage : buffer structure pointer, if param is NULL, then it will set tx_buf to NULL + * - Return value explanation : + */ +#define UART_CMD_SET_TXINT_BUF DEV_SET_SYSCMD(14) +/** + * Set receive buffer via interrupt, and it will set \ref dev_uart_info::rx_buf "rx_buf" + * - Param type : DEV_BUFFER * or NULL + * - Param usage : buffer structure pointer, if param is NULL, then it will set rx_buf to NULL + * - Return value explanation : + */ +#define UART_CMD_SET_RXINT_BUF DEV_SET_SYSCMD(15) +/** + * Enable or disable transmit interrupt + * - Param type : uint32_t + * - Param usage : enable(none-zero) or disable(zero) flag + * - Return value explanation : + */ +#define UART_CMD_SET_TXINT DEV_SET_SYSCMD(16) +/** + * Enable or disable receive interrupt + * - Param type : uint32_t + * - Param usage : enable(none-zero) or disable(zero) flag + * - Return value explanation : + */ +#define UART_CMD_SET_RXINT DEV_SET_SYSCMD(17) +/** + * Abort current interrupt transmit operation if tx interrupt enabled, + * it will disable transmit interrupt, and set \ref DEV_IN_TX_ABRT + * in \ref dev_uart_info::status "status" variable, + * and call the transmit callback function, when tx callback is finished, + * it will clear \ref DEV_IN_TX_ABRT and return + * - Param type : NULL + * - Param usage : + * - Return value explanation : + */ +#define UART_CMD_ABORT_TX DEV_SET_SYSCMD(18) +/** + * Abort current interrupt receive operation if rx interrupt enabled, + * it will disable receive interrupt, and set \ref DEV_IN_TX_ABRT + * in \ref dev_uart_info::status "status" variable, + * and call the receive callback function, when rx callback is finished, + * it will clear \ref DEV_IN_TX_ABRT and return + * - Param type : NULL + * - Param usage : + * - Return value explanation : + */ +#define UART_CMD_ABORT_RX DEV_SET_SYSCMD(19) + +/** @} */ + +/** + * \defgroup DEVICE_HAL_UART_CALLBACK UART Interrupt callback functions + * \ingroup DEVICE_HAL_UART + * \brief callback function structure for UART device + * @{ + */ +typedef struct dev_uart_cbs { + DEV_CALLBACK tx_cb; /*!< uart data transmit success required bytes callback */ + DEV_CALLBACK rx_cb; /*!< uart data receive success required bytes callback */ + DEV_CALLBACK err_cb; /*!< uart error callback */ +} DEV_UART_CBS, *DEV_UART_CBS_PTR; +/** @} */ + +/** + * \defgroup DEVICE_HAL_UART_DEVSTRUCT UART Device Interface Definition + * \ingroup DEVICE_HAL_UART + * \brief Contains definitions of uart device interface structure. + * \details This structure will be used in user implemented code, which was called + * \ref DEVICE_IMPL "Device Driver Implement Layer" for uart to use in implementation code. + * Application developer should use the UART API provided here to access to UART devices. + * BSP developer should follow the API definition to implement UART device drivers. + * @{ + */ +/** + * \brief UART information struct definition + * \details informations about uart open count, working status, + * baudrate, uart registers and ctrl structure, uart dps format + */ +typedef struct dev_uart_info { + void *uart_ctrl; /*!< uart control related pointer, implemented by bsp developer, and this should be set during uart object implementation */ + uint32_t opn_cnt; /*!< uart open count, open it will increase 1, close it will decrease 1, 0 for close, >0 for open */ + uint32_t status; /*!< current working status, refer to \ref DEVICE_HAL_COMMON_DEVSTATUS, this should be \ref DEV_ENABLED for first open */ + uint32_t baudrate; /*!< uart baud rate, this should be the value of baud passing by uart_open if first successfully opened */ + UART_DPS_FORMAT dps_format; /*!< D/P/S format settings for uart device, here is \ref dps_format_default "default settings for first open" */ + UART_HW_FLOW_CONTROL hwfc; /*!< UART hardware flow control, here is \ref hwfc_default "default hardware flow control settings for first open" */ + DEV_BUFFER tx_buf; /*!< transmit buffer via interrupt, this should be all zero for first open */ + DEV_BUFFER rx_buf; /*!< receive buffer via interrupt, this should be all zero for first open */ + DEV_UART_CBS uart_cbs; /*!< uart callbacks, callback arguments should be \ref DEV_UART * or NULL, this should be all NULL for first open */ + void *extra; /*!< a extra pointer to get hook to applications which should not used by bsp developer, + this should be NULL for first open and you can \ref DEV_UART_INFO_SET_EXTRA_OBJECT "set" + or \ref DEV_UART_INFO_GET_EXTRA_OBJECT "get" the extra information pointer */ +} DEV_UART_INFO, * DEV_UART_INFO_PTR; + +/** Set extra information pointer of uart info */ +#define DEV_UART_INFO_SET_EXTRA_OBJECT(uart_info_ptr, extra_info) (uart_info_ptr)->extra = (void *)(extra_info) +/** Get extra information pointer of uart info */ +#define DEV_UART_INFO_GET_EXTRA_OBJECT(uart_info_ptr) ((uart_info_ptr)->extra) + +/** + * \brief UART device interface definition + * \details Define uart device interface, like uart information structure, + * provide functions to open/close/control uart, send/receive data by uart + * \note All this details are implemented by user in user porting code + */ +typedef struct dev_uart { + DEV_UART_INFO uart_info; /*!< UART device information */ + int32_t (*uart_open) (uint32_t baud); /*!< Open uart device */ + int32_t (*uart_close) (void); /*!< Close uart device */ + int32_t (*uart_control) (uint32_t ctrl_cmd, void *param); /*!< Control uart device */ + int32_t (*uart_write) (const void *data, uint32_t len); /*!< Send data by uart device(blocked) */ + int32_t (*uart_read) (void *data, uint32_t len); /*!< Read data from uart device(blocked) */ +} DEV_UART, * DEV_UART_PTR; + +/** + * \fn int32_t (* dev_uart::uart_open) (uint32_t baud) + * \details open an uart device with defined baudrate + * \param[in] baud \ref DEVICE_HAL_UART_BAUD "initial baudrate of uart", must > 0 + * \retval E_OK Open successfully without any issues + * \retval E_OPNED If device was opened before with different parameters, + * then just increase the \ref dev_uart_info::opn_cnt "opn_cnt" and return \ref E_OPNED + * \retval E_OBJ Device object is not valid + * \retval E_PAR Parameter is not valid + * \retval E_NOSPT Open settings are not supported + */ + +/** + * \fn int32_t (* dev_uart::uart_close) (void) + * \details close an uart device, just decrease the \ref dev_uart_info::opn_cnt "opn_cnt", + * if \ref dev_uart_info::opn_cnt "opn_cnt" equals 0, then close the device + * \retval E_OK Close successfully without any issues(including scenario that device is already closed) + * \retval E_OPNED Device is still opened, the device \ref dev_uart_info::opn_cnt "opn_cnt" decreased by 1 + * \retval E_OBJ Device object is not valid + */ + +/** + * \fn int32_t (* dev_uart::uart_control) (uint32_t ctrl_cmd, void *param) + * \details control an uart device by \ref ctrl_cmd, with passed \ref param. + * you can control uart device using predefined uart control commands defined using \ref DEV_SET_SYSCMD + * (which must be implemented by bsp developer), such as \ref UART_CMD_SET_BAUD "change baudrate", + * \ref UART_CMD_FLUSH_OUTPUT "flush output" and \ref DEVICE_HAL_UART_CTRLCMD "more". + * And you can also control uart device using your own specified commands defined using \ref DEV_SET_USRCMD, + * but these specified commands should be defined in your own uart device driver implementation. + * \param[in] ctrl_cmd \ref DEVICE_HAL_UART_CTRLCMD "control command", to change or get some thing related to uart + * \param[in,out] param parameters that maybe argument of the command, or return values of the command + * \retval E_OK Control device successfully + * \retval E_CLSED Device is not opened + * \retval E_OBJ Device object is not valid or not exists + * \retval E_PAR Parameter is not valid for current control command + * \retval E_SYS Control device failed, due to hardware issues, such as device is disabled + * \retval E_CTX Control device failed, due to different reasons like in transfer state + * \retval E_NOSPT Control command is not supported or not valid + */ + +/** + * \fn int32_t (* dev_uart::uart_write) (const void *data, uint32_t len) + * \details send \ref data through uart with defined \ref len(blocked). + * \param[in] data pointer to data need to send by uart, must not be NULL + * \param[in] len length of data to be sent, must > 0 + * \retval >0 Byte count that was successfully sent for poll method + * \retval E_OBJ Device object is not valid or not exists + * \retval E_PAR Parameter is not valid + * \retval E_SYS Can't write data to hardware due to hardware issues, such as device is disabled + */ + +/** + * \fn int32_t (* dev_uart::uart_read) (void *data, uint32_t len) + * \details receive \ref data of defined \ref len through uart(blocked). + * \param[out] data pointer to data need to received by uart, must not be NULL + * \param[in] len length of data to be received, must > 0 + * \retval >0 Byte count that was successfully received for poll method + * \retval E_OBJ Device object is not valid or not exists + * \retval E_PAR Parameter is not valid + * \retval E_SYS Can't receive data from hardware due to hardware issues, such as device is disabled + */ +/** @} */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief get an \ref dev_uart "uart device" by uart device id. + * For how to use uart device hal refer to \ref DEVICE_HAL_UART_DEVSTRUCT "Functions in uart device structure" + * \param[in] uart_id id of uart, defined by user + * \retval !NULL pointer to an \ref dev_uart "uart device structure" + * \retval NULL failed to find the uart device by \ref uart_id + * \note need to implemented by user in user code + */ +extern DEV_UART_PTR uart_get_dev(int32_t uart_id); + +#ifdef __cplusplus +} +#endif + +/** @} */ +#endif /* _DEVICE_HAL_UART_H_ */ diff --git a/hw/mcu/arc/src/ext/sdk/inc/arc/arc.h b/hw/mcu/arc/src/ext/sdk/inc/arc/arc.h new file mode 100644 index 000000000..91c0a3850 --- /dev/null +++ b/hw/mcu/arc/src/ext/sdk/inc/arc/arc.h @@ -0,0 +1,436 @@ +/* ------------------------------------------ + * Copyright (c) 2016, Synopsys, Inc. All rights reserved. + + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + + * 1) Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + + * 2) 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. + + * 3) Neither the name of the Synopsys, Inc., nor the names of its contributors may + * be used to endorse or promote products derived from this software without + * specific prior written permission. + + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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. + * + * \version 2016.05 + * \date 2014-06-20 + * \author Wayne Ren(Wei.Ren@synopsys.com) +--------------------------------------------- */ + +/** + * \file + * \ingroup ARC_HAL_CORE_COMM + * \brief header file including common core definitions + */ + + /** + * \addtogroup ARC_HAL_CORE_COMM + * @{ + */ + + +#ifndef _ARC_HAL_CORE_H_ +#define _ARC_HAL_CORE_H_ + +#include "inc/arc/arc_feature_config.h" + +/** + * \name exception number definitions + * @{ + */ + +/* ARC exception number */ +#define EXC_NO_RESET (0) /*!< reset vector, the entry of power up and reset */ +#define EXC_NO_MEM_ERR (1) /*!< external memory bus error */ +#define EXC_NO_INS_ERR (2) /*!< illegal instruction or illegal instruction sequence */ +#define EXC_NO_MAC_CHK (3) /*!< machine check error */ +#define EXC_NO_TLB_MISS_I (4) /*!< instruction TLB missing exception, useless without MMU */ +#define EXC_NO_TLB_MISS_D (5) /*!< data TLB missing exception, useless without MMU */ +#define EXC_NO_PRO_VIO (6) /*!< protection violation */ +#define EXC_NO_PRI_VIO (7) /*!< privilege violation */ +#define EXC_NO_SWI (8) /*!< software interrupt */ +#define EXC_NO_TRAP (9) /*!< trap */ +#define EXC_NO_EXT (10) /*!< extension exception */ +#define EXC_NO_DIV_ZER0 (11) /*!< divide by zero */ +#define EXC_NO_DC_ERR (12) /*!< data cache consistency error */ +#define EXC_NO_MAL_ALIGN (13) /*!< misaligned data access */ +#define EXC_NO_RESERVE0 (14) /*!< reserved */ +#define EXC_NO_RESERVE1 (15) /*!< reserved */ + +/* extension interrupts */ +#define EXC_NO_16 (16) /*!< interrupt vector 16 */ +#define EXC_NO_17 (17) /*!< interrupt vector 17 */ +#define EXC_NO_18 (18) /*!< interrupt vector 18 */ +#define EXC_NO_19 (19) /*!< interrupt vector 19 */ +#define EXC_NO_20 (20) /*!< interrupt vector 20 */ +#define EXC_NO_21 (21) /*!< interrupt vector 21 */ +#define EXC_NO_22 (22) /*!< interrupt vector 22 */ +#define EXC_NO_23 (23) /*!< interrupt vector 23 */ +#define EXC_NO_24 (24) /*!< interrupt vector 24 */ +#define EXC_NO_25 (25) /*!< interrupt vector 25 */ +#define EXC_NO_26 (26) /*!< interrupt vector 26 */ +#define EXC_NO_27 (27) /*!< interrupt vector 27 */ +#define EXC_NO_28 (28) /*!< interrupt vector 28 */ +#define EXC_NO_29 (29) /*!< interrupt vector 29 */ +#define EXC_NO_30 (30) /*!< interrupt vector 30 */ +#define EXC_NO_31 (31) /*!< interrupt vector 31 */ +/* ... ARC supports 255 interrupt vectors at most */ +#define EXC_NO_255 (255) /*!< interrupt vector 255 */ + +/** @} */ + +/** + * \name exception vector offset + * @{ + */ +#define EXC_NO_TO_OFFSET(no) (no << 2) + +/* ARC exception vector offset */ +#define EXC_VECTOR_RESET (0x00) /*!< EXC_NO_RESET offset */ +#define EXC_VECTOR_MEM_ERR (0x04) /*!< EXC_NO_MEM_ERR offset */ +#define EXC_VECTOR_INS_ERR (0x08) /*!< EXC_NO_INS_ERR offset */ +#define EXC_VECTOR_MAC_CHK (0x0c) /*!< EXC_NO_MAC_CHK offset */ +#define EXC_VECTOR_TLB_MISS_I (0x10) /*!< EXC_NO_TLB_MISS_I offset */ +#define EXC_VECTOR_TLB_MISS_D (0x14) /*!< EXC_NO_TLB_MISS_D offset */ +#define EXC_VECTOR_PRO_VIO (0x18) /*!< EXC_NO_PRO_VIO offset */ +#define EXC_VECTOR_PRI_VIO (0x1c) /*!< EXC_NO_PRI_VIO offset */ +#define EXC_VECTOR_SWI (0x20) /*!< EXC_NO_SWI offset */ +#define EXC_VECTOR_TRAP (0x24) /*!< EXC_NO_TRAP offset */ +#define EXC_VECTOR_EXT (0x28) /*!< EXC_NO_EXT offset */ +#define EXC_VECTOR_DIV_ZER0 (0x2c) /*!< EXC_NO_DIV_ZER0 offset */ +#define EXC_VECTOR_DC_ERR (0x30) /*!< EXC_NO_DC_ERR offset */ +#define EXC_VECTOR_MAL_ALIGN (0x34) /*!< EXC_NO_MAL_ALIGN offset */ +#define EXC_VECTOR_RESERVE0 (0x38) /*!< EXC_NO_RESERVE0 offset */ +#define EXC_VECTOR_RESERVE1 (0x3c) /*!< EXC_NO_RESERVE1 offset */ +/** @} */ + +/** + * \name build configuration register + * @{ + */ +#define AUX_BCR_VER (0x60) /*!< build configuration register version */ +#define AUX_BCR_BTA (0x63) /*!< build configuration for BTA LINK */ +#define AUX_BCR_VECBASE (0x68) /*!< build configuration for interrupt vector base */ +#define AUX_BCR_MPU (0x6d) /*!< build configuration for memory protection unit */ +#define AUX_BCR_RF (0x6e) /*!< build configuration for core registers */ +#define AUX_BCR_D_CACHE (0x72) /*!< build configuration for data cache */ +#define AUX_BCR_DCCM (0x74) /*!< build configuration for DCCM */ +#define AUX_BCR_TIMERS (0x75) /*!< build configuration for processor timers */ +#define AUX_BCR_AP (0x76) /*!< build configuration for actionpoints */ +#define AUX_BCR_I_CACHE (0x77) /*!< build configuration for instruction cache */ +#define AUX_BCR_ICCM (0x78) /*!< build configuration for ICCM */ +#define AUX_BCR_DSP (0x7a) /*!< build configuration for DSP */ +#define AUX_BCR_MUL (0x7b) /*!< build configuration for multiply */ +#define AUX_BCR_SWAP (0x7c) /*!< build configuration for swap */ +#define AUX_BCR_NORM (0x7d) /*!< build configuration for normalize */ +#define AUX_BCR_MIXMAX (0x7e) /*!< build configuration for MIN/MAX */ +#define AUX_BCR_BARREL (0x7f) /*!< build configuration for barrel shift */ +#define AUX_BCR_ISA (0xc1) /*!< build configuration for ISA configuration */ +#define AUX_BCR_STACK (0xc5) /*!< build configuration for stack region */ +#define AUX_BCR_ERP (0xc7) /*!< build configuration for error protection */ +#define AUX_BCR_FPU (0xc8) /*!< build configuration for floating-point unit */ +#define AUX_BCR_CPORT (0xc9) /*!< build configuration for code protection */ +#define AUX_BCR_BS (0xcb) /*!< build configuration for bitstream */ +#define AUX_BCR_AGU (0xcc) /*!< build configuration for address generate unit */ +#define AUX_BCR_DMAC (0xcd) /*!< build configuration for DMA */ +#define AUX_BCR_CONNECT_SYSTEM (0xd0) /*!< build configuration for arc connect */ +#define AUX_BCR_CONNECT_SEMA (0xd1) /*!< build configuration for inter-core semaphore */ +#define AUX_BCR_CONNECT_MESSAGE (0xd2) /*!< build configuration for inter-code message */ +#define AUX_BCR_CONNECT_PMU (0xd3) /*!< build configuration for power management unit */ +#define AUX_BCR_CONNECT_GFRC (0xd6) /*!< build configuration for global free running counter */ +#define AUX_BCR_CAL_STORE (0xd9) /*!< build configuration for calibration parameter storage */ +#define AUX_BCR_CONNECT_ICI (0xe0) /*!< build configuration for inter-core interrupt unit */ +#define AUX_BCR_CONNECT_ICD (0xe1) /*!< build configuration for inter-core debug unit */ +#define AUX_BCR_CONNECT_PDM (0xe3) /*!< build configuration for power domain management unit*/ +#define AUX_BCR_RTT (0xf2) /*!< build configuration for real-time trace */ +#define AUX_BCR_IRQ (0xf3) /*!< build configuration for interrupt */ +#define AUX_BCR_PCT (0xf5) /*!< build configuration for performance counters */ +#define AUX_BCR_CC (0xf6) /*!< build configuration for performance counters */ +#define AUX_BCR_PDM_DVFS (0xf7) /*!< build configuration for PDM and DVFS */ + +#define AUX_BCR_SEC_BUILD (0xdb) + +/* from 0xF5 and 0xF6 */ + +#define AUX_BCR_IFQUEUE (0xfe) /*!< build configuration for instruction fetch queue */ +#define AUX_BCR_SMART (0xff) /*!< build configuration for SmaRT debug feature */ +/** @} */ + + +#define AUX_SEC_STAT (0x9) +#define AUX_SEC_STAT_BIT_SSC (0) +#define AUX_SEC_STAT_BIT_NSRT (1) +#define AUX_SEC_STAT_BIT_NSRU (2) +#define AUX_SEC_STAT_BIT_IRM (3) +#define AUX_SEC_STAT_BIT_SUE (4) +#define AUX_SEC_STAT_BIT_NIC (5) + +/** + * \name status register STATUS32 + * @{ + */ +#define AUX_STATUS32 (0xa) +#define AUX_STATUS32_P0 (0xb) + +/* STATUS32 bit-field definition */ +#define AUX_STATUS_BIT_AE (5) /*!< processor is in an exception */ +#define AUX_STATUS_BIT_DE (6) /*!< delayed branch is pending */ +#define AUX_STATUS_BIT_U (7) /*!< user mode */ +#define AUX_STATUS_BIT_L (12) /*!< zero-overhead loop enable */ +#define AUX_STATUS_BIT_IE (31) /*!< interrupt enable */ + +/* masks correspond to STATUS32 bit-field */ +#define AUX_STATUS_MASK_AE (1< Pre Incr + * Eff Addr for load = [reg2 + x] + * + * LD.ab reg1, [reg2, x] => Post Incr + * Eff Addr for load = [reg2] + */ +#if defined(__GNU__) +.macro PUSH reg + st.a \reg, [sp, -4] +.endm + +.macro PUSHAX aux + lr r10, [\aux] + PUSH r10 +.endm + +.macro POP reg + ld.ab \reg, [sp, 4] +.endm + +.macro POPAX aux + POP r10 + sr r10, [\aux] +.endm +#else +.macro PUSH, reg + st.a reg, [sp, -4] +.endm + +.macro PUSHAX, aux + lr r10, [aux] + PUSH r10 +.endm + +.macro POP, reg + ld.ab reg, [sp, 4] +.endm + +.macro POPAX, aux + POP r10 + sr r10, [aux] +.endm +#endif + +/*-------------------------------------------------------------- + * Helpers to save/restore callee-saved regs: + * used by several macros below + *-------------------------------------------------------------*/ +.macro SAVE_CALLEE_REGS + PUSH r13 + PUSH r14 + PUSH r15 +#ifndef ARC_FEATURE_RF16 + PUSH r16 + PUSH r17 + PUSH r18 + PUSH r19 + PUSH r20 + PUSH r21 + PUSH r22 + PUSH r23 + PUSH r24 + PUSH r25 +#endif +.endm + +.macro RESTORE_CALLEE_REGS +#ifndef ARC_FEATURE_RF16 + POP r25 + POP r24 + POP r23 + POP r22 + POP r21 + POP r20 + POP r19 + POP r18 + POP r17 + POP r16 +#endif + POP r15 + POP r14 + POP r13 +.endm + +.macro CLEAR_CALLEE_REGS +#ifndef ARC_FEATURE_RF16 + mov r25, 0 + mov r24, 0 + mov r23, 0 + mov r22, 0 + mov r21, 0 + mov r20, 0 + mov r19, 0 + mov r18, 0 + mov r17, 0 + mov r16, 0 +#endif + mov r15, 0 + mov r14, 0 + mov r13, 0 +.endm + +.macro CLEAR_SCRATCH_REGS + mov r1, 0 + mov r2, 0 + mov r3, 0 + mov r4, 0 + mov r5, 0 + mov r6, 0 + mov r7, 0 + mov r8, 0 + mov r9, 0 + mov r10, 0 + mov r11, 0 + mov r12, 0 + + mov fp, 0 + mov r29, 0 + mov r30, 0 +.endm + + +.macro SAVE_LP_REGS + PUSH r60 + PUSHAX AUX_LP_START + PUSHAX AUX_LP_END +.endm + +.macro RESTORE_LP_REGS + POPAX AUX_LP_END + POPAX AUX_LP_START + POP r10 +/* must not use the LP_COUNT register(r60) as the destination of multi-cycle instruction */ + mov r60, r10 + +.endm + +.macro SAVE_R0_TO_R12 + PUSH r0 + PUSH r1 + PUSH r2 + PUSH r3 +#ifndef ARC_FEATURE_RF16 + PUSH r4 + PUSH r5 + PUSH r6 + PUSH r7 + PUSH r8 + PUSH r9 +#endif + PUSH r10 + PUSH r11 + PUSH r12 +.endm + +.macro RESTORE_R0_TO_R12 + POP r12 + POP r11 + POP r10 +#ifndef ARC_FEATURE_RF16 + POP r9 + POP r8 + POP r7 + POP r6 + POP r5 + POP r4 +#endif + POP r3 + POP r2 + POP r1 + POP r0 +.endm + +.macro SAVE_CODE_DENSITY + PUSHAX AUX_JLI_BASE + PUSHAX AUX_LDI_BASE + PUSHAX AUX_EI_BASE +.endm + +.macro RESTORE_CODE_DENSITY + POPAX AUX_EI_BASE + POPAX AUX_LDI_BASE + POPAX AUX_JLI_BASE +.endm + +/* todo: check the contents of NON_SCRATCH_REGS in debug */ +.macro SAVE_NONSCRATCH_REGS +/* r0-r12 are saved by caller function */ + PUSH gp + PUSH fp + PUSH blink + SAVE_CALLEE_REGS +.endm + +.macro RESTORE_NONSCRATCH_REGS + RESTORE_CALLEE_REGS + POP blink + POP fp + POP gp +.endm + + +.macro SAVE_FIQ_EXC_REGS +#ifndef ARC_FEATURE_RGF_BANKED_REGS + SAVE_R0_TO_R12 + + PUSH gp + PUSH fp + PUSH r30 /* general purpose */ + PUSH blink + +#else +#if ARC_FEATURE_RGF_BANKED_REGS != 4 && ARC_FEATURE_RGF_BANKED_REGS != 8 && \ + ARC_FEATURE_RGF_BANKED_REGS != 16 && ARC_FEATURE_RGF_BANKED_REGS != 32 +#error "unsupported ARC_FEATURE_RGF_BANKED_REGS" +#endif + +#if ARC_FEATURE_RGF_BANKED_REGS == 4 || ARC_FEATURE_BANKED_REGS == 8 || \ + ARC_FEATURE_RGF_BANKED_REGS == 16 + PUSH r4 + PUSH r5 + PUSH r6 + PUSH r7 + PUSH r8 + PUSH r9 +#endif + +#if ARC_FEATURE_RGF_BANKED_REGS == 4 || ARC_FEATURE_BANKED_REGS == 8 + PUSH r10 + PUSH r11 +#endif + +#if ARC_FEATURE_RGF_BANKED_REGS == 4 + PUSH r12 +#endif + +#if ARC_FEATURE_RGF_BANKED_REGS == 4 || ARC_FEATURE_BANKED_REGS == 8 + PUSH gp + PUSH fp + PUSH r30 /* general purpose */ + PUSH blink +#endif + +#endif /* #ifndef ARC_FEATURE_RGF_BANKED_REGS */ + +#ifdef ARC_FEATURE_CODE_DENSITY + SAVE_CODE_DENSITY +#endif + SAVE_LP_REGS +.endm + +.macro RESTORE_FIQ_EXC_REGS + RESTORE_LP_REGS +#ifdef ARC_FEATURE_CODE_DENSITY + RESTORE_CODE_DENSITY +#endif + +#ifndef ARC_FEATURE_RGF_BANKED_REGS + POP blink + POP r30 + POP fp + POP gp + + RESTORE_R0_TO_R12 +#else + +#if ARC_FEATURE_RGF_BANKED_REGS != 4 && ARC_FEATURE_RGF_BANKED_REGS != 8 && \ + ARC_FEATURE_RGF_BANKED_REGS != 16 && ARC_FEATURE_RGF_BANKED_REGS != 32 +#error "unsupported ARC_FEATURE_RGF_BANKED_REGS" +#endif + +#if ARC_FEATURE_RGF_BANKED_REGS == 4 || ARC_FEATURE_BANKED_REGS == 8 + POP blink + POP r30 + POP fp + POP gp +#endif + +#if ARC_FEATURE_RGF_BANKED_REGS == 4 + POP r12 +#endif + +#if ARC_FEATURE_RGF_BANKED_REGS == 4 || ARC_FEATURE_BANKED_REGS == 8 + POP r11 + POP r10 +#endif + +#if ARC_FEATURE_RGF_BANKED_REGS == 4 || ARC_FEATURE_BANKED_REGS == 8 || \ + ARC_FEATURE_RGF_BANKED_REGS == 16 + POP r9 + POP r8 + POP r7 + POP r6 + POP r5 + POP r4 +#endif + +#endif /* #ifndef ARC_FEATURE_RGF_BANKED_REGS */ +.endm + +/* normal interrupt prologue, pc, status and r0-r11 are saved by hardware */ +.macro INTERRUPT_PROLOGUE + PUSH r12 + PUSH gp + PUSH fp + PUSH ilink + PUSH r30 + + sub sp, sp, 4 /* skip bta */ +.endm + + +/* normal interrupt epilogue, pc, status and r0-r11 are restored by hardware */ +.macro INTERRUPT_EPILOGUE + add sp, sp, 4 /* skip bta */ + + POP r30 + POP ilink + POP fp + POP gp + POP r12 +.endm + +#if SECURESHIELD_VERSION == 2 +/* exception prologue, create the same frame of interrupt manually */ +.macro EXCEPTION_PROLOGUE + st.as r10, [sp, -6] /* save r10 first, free up a register*/ + + PUSHAX AUX_ERSTATUS + sub sp, sp, 4 /* slot for SEC_STAT */ + PUSHAX AUX_ERRET + + PUSH blink + + PUSH r11 + sub sp, sp, 4 /* r10 is pushed before */ +#ifndef ARC_FEATURE_RF16 + PUSH r9 + PUSH r8 + PUSH r7 + PUSH r6 + PUSH r5 + PUSH r4 +#endif + PUSH r3 + PUSH r2 + PUSH r1 + PUSH r0 + +#ifdef ARC_FEATURE_CODE_DENSITY + SAVE_CODE_DENSITY +#endif + SAVE_LP_REGS + + PUSH r12 + PUSH gp + PUSH fp + PUSH ilink + PUSH r30 + + PUSHAX AUX_ERBTA +.endm + +/* exception epilogue, restore the same frame of interrupt manually */ +.macro EXCEPTION_EPILOGUE + POPAX AUX_ERBTA + + POP r30 + POP ilink + POP fp + POP gp + POP r12 + + RESTORE_LP_REGS + +#ifdef ARC_FEATURE_CODE_DENSITY + RESTORE_CODE_DENSITY +#endif + POP r0 + POP r1 + POP r2 + POP r3 +#ifndef ARC_FEATURE_RF16 + POP r4 + POP r5 + POP r6 + POP r7 + POP r8 + POP r9 +#endif + add sp, sp, 4 /* r10 will be popped finally */ + POP r11 + + POP blink + + + POPAX AUX_ERRET + add sp, sp, 4 /* slot for SEC_STAT */ + POPAX AUX_ERSTATUS + + ld.as r10, [sp, -6] /* restore r10 */ +.endm +#else /* normal version */ +/* exception prologue, create the same frame of interrupt manually */ +.macro EXCEPTION_PROLOGUE +#ifdef ARC_FEATURE_CODE_DENSITY + st.as r10, [sp, -11] /* save r10 first, free up a register*/ +#else + st.as r10, [sp, -8] +#endif + PUSHAX AUX_ERSTATUS + PUSHAX AUX_ERRET + +#ifdef ARC_FEATURE_CODE_DENSITY + SAVE_CODE_DENSITY +#endif + SAVE_LP_REGS + + PUSH blink + + PUSH r11 + sub sp, sp, 4 /* r10 is pushed before */ +#ifndef ARC_FEATURE_RF16 + PUSH r9 + PUSH r8 + PUSH r7 + PUSH r6 + PUSH r5 + PUSH r4 +#endif + PUSH r3 + PUSH r2 + PUSH r1 + PUSH r0 + + PUSH r12 + PUSH gp + PUSH fp + PUSH ilink + PUSH r30 + + PUSHAX AUX_ERBTA +.endm + +/* exception epilogue, restore the same frame of interrupt manually */ +.macro EXCEPTION_EPILOGUE + POPAX AUX_ERBTA + + POP r30 + POP ilink + POP fp + POP gp + POP r12 + + POP r0 + POP r1 + POP r2 + POP r3 +#ifndef ARC_FEATURE_RF16 + POP r4 + POP r5 + POP r6 + POP r7 + POP r8 + POP r9 +#endif + add sp, sp, 4 /* r10 will be popped finally */ + POP r11 + + POP blink + + RESTORE_LP_REGS + +#ifdef ARC_FEATURE_CODE_DENSITY + RESTORE_CODE_DENSITY +#endif + + POPAX AUX_ERRET + POPAX AUX_ERSTATUS + +#ifdef ARC_FEATURE_CODE_DENSITY + ld.as r10, [sp, -11] /* restore r10 */ +#else + ld.as r10, [sp, -8] +#endif +.endm + +#endif /* SECURESHIELD_VERSION == 2 */ + +#endif /* _ARC_HAL_ASM_COMMON_H */ +/** @endcond */ diff --git a/hw/mcu/arc/src/ext/sdk/inc/arc/arc_builtin.h b/hw/mcu/arc/src/ext/sdk/inc/arc/arc_builtin.h new file mode 100644 index 000000000..d9b76124f --- /dev/null +++ b/hw/mcu/arc/src/ext/sdk/inc/arc/arc_builtin.h @@ -0,0 +1,301 @@ +/* ------------------------------------------ + * Copyright (c) 2016, Synopsys, Inc. All rights reserved. + + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + + * 1) Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + + * 2) 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. + + * 3) Neither the name of the Synopsys, Inc., nor the names of its contributors may + * be used to endorse or promote products derived from this software without + * specific prior written permission. + + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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. + * + * \version 2016.05 + * \date 2014-06-12 + * \author Wayne Ren(Wei.Ren@synopsys.com) +--------------------------------------------- */ + +/** + * \file + * \ingroup ARC_HAL_BUILTIN + * \brief header file of builtin and helper functions + * + * The Metaware toolchain and the GNU toolchain are supported. The details please go to see the file. + */ + +/** + * \addtogroup ARC_HAL_BUILTIN + * @{ + */ + +#ifndef _ARC_HAL_BUILTIN_H_ +#define _ARC_HAL_BUILTIN_H_ + +#include "inc/embARC_toolchain.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#if defined (__MW__) /* Metaware toolchain */ + +#define _arc_nop _nop /*!< no operation, generate a nop instruction produces a single NOP instruction in the compiled code */ + +#define _arc_brk _brk /*!< generate a brk instruction */ + +#define _arc_clri _clri /*!< generate a clri instruction */ + +#define _arc_seti(c) _seti(c) /*!< generate a seti instruction */ + +#define _arc_core_write(regno, val) _core_write(val, regno) /*!< write core register */ + +#define _arc_core_read(regno) _core_read(regno) /*!< read core register */ + +#define _arc_lr_reg(aux) _lr(aux) /*!< read auxiliary register */ + +#define _arc_sr_reg(aux, val) _sr(val, aux) /*!< write auxiliary register */ + +#define _arc_sleep(a) _sleep(a) /*!< generate a sleep instruction */ + +#define _arc_flag(a) _flag(a) /*!< generate a flag instruction */ + +#define _arc_kflag(a) + +#define _arc_sync _sync /*!< generate a sync instruction */ + +/* + * !< _arc_usually (expr) evaluates expression expr and + * informs the compiler that the value is usually true. + */ +#define _arc_usually(a) _Usually((a)) + +/* + * !< _arc_rarely (expr) evaluates expression expr and + * informs the compiler that the value is rarely true. + */ +#define _arc_rarely(a) _Rarely((a)) + +#if 0 +/** + * \brief Reverses the byte order of the 16-bit operand, + * reversing the endianness of the value. + * Not for ARC HS family + */ +#define _arc_swap16(a) _swap16(a) +/** + * \brief Reverses the byte order of the 32-bit operand, + * reversing the endianness of the value. + * Not for ARC HS family + */ +#define _arc_swap32(a) _swap32(a) +#else +Inline uint32_t _arc_swap32(uint32_t val) { + register uint32_t v; + __asm__ volatile ("swape %0, %1" :"=r"(v): "r"(val)); + return v; +} + +Inline uint16_t _arc_swap16(uint32_t val) { + register uint32_t temp; + register uint32_t v; + __asm__ volatile ("swape %0, %1" :"=r"(temp): "r"(val)); + __asm__ volatile ("lsr16 %0, %1" :"=r"(v): "r"(temp)); + return (unsigned short)v; +} +#endif + +/** + * \brief Each call to _swi() generates one + * software interrupt instruction (SWI) for processors + * to support the SWI instruction. + */ +#define _arc_swi _swi + +/* \todo add more builtin functions of metaware tool */ + +#elif defined (__GNU__) /* GNU toolchain */ + +#define _arc_nop __builtin_arc_nop +#define _arc_brk __builtin_arc_brk +#define _arc_seti(c) __builtin_arc_seti(c) +#define _arc_core_write(regno, val) __builtin_arc_core_write(regno,val) +#define _arc_core_read(regno) __builtin_arc_core_read(regno) +#define _arc_flag(a) __builtin_arc_flag(a) +#define _arc_kflag(a) __builtin_arc_kflag(a) +#define _arc_lr_reg(aux) __builtin_arc_lr(aux) +/* don't uncomment this now */ +//#define _arc_sr_reg(aux, val) __builtin_arc_sr(aux, val) +#define _arc_sleep(a) __builtin_arc_sleep(a) +//#define _arc_sync __builtin_arc_sync + +/** + * \brief _arc_usually (expr) evaluates expression expr and + * informs the compiler that the value is usually true. + */ +#define _arc_usually(a) __builtin_expect((int)(a), 1) + +/** + * \brief _arc_rarely (expr) evaluates expression expr and + * informs the compiler that the value is rarely true. + */ +#define _arc_rarely(a) __builtin_expect((int)(a), 0) + +/** + * \brief Each call to _swi() generates one + * software interrupt instruction (SWI) for processors + * to support the SWI instruction. + */ +#define _arc_swi __builtin_arc_swi + +Inline uint32_t _arc_clri(void) { + register uint32_t v; + __asm__ volatile ("clri %0" :"=r"(v)); + return v; + +} +/* \todo add more builtin functions of gnu tool */ + +Inline uint32_t _arc_swap32(uint32_t val) { + register uint32_t v; + __asm__ volatile ("swape %0, %1" :"=r"(v): "r"(val)); + return v; +} + +Inline uint16_t _arc_swap16(uint32_t val) { + register uint32_t temp; + register uint32_t v; + __asm__ volatile ("swape %0, %1" :"=r"(temp): "r"(val)); + __asm__ volatile ("lsr16 %0, %1" :"=r"(v): "r"(temp)); + return (unsigned short)v; +} + +Inline void _arc_sync(void) { + __asm__ volatile ("sync"); +} + +/** + * \note Following is a workaround for arc gcc + * built-in function __builtin_arc_sr. + * But it is wrong in GCC arc-4.8-R3-rc3 and shouldn't be used. + */ + +/* + * The auxiliary register address is specified as a long immediate operand by caller. + * e.g. + * write_aux_reg(0x69, some_val); + * This generates the tightest code. + */ +#define write_aux_reg(reg_imm, val) \ +({ \ + Asm( \ + " sr %0, [%1] \n" \ + : \ + : "ir"(val), "r"(reg_imm)); \ +}) + +#define _arc_sr_reg(aux, val) write_aux_reg(aux, val) + +#endif + +/* \todo add more helper functions here, such as memory operation */ + +#define _arc_aux_read(aux) _arc_lr_reg(aux) +#define _arc_aux_write(aux, val) _arc_sr_reg(aux, val) + +/** + * \name cache related helper function + * @{ + */ + +/** + * \brief read memory and bypass the cache + * \param[in] ptr memory address + * \return value in the memory + */ +Inline uint32_t _arc_read_uncached_32(void *ptr) +{ + uint32_t __ret; + Asm("ld.di %0, [%1]":"=r"(__ret):"r"(ptr)); + return __ret; +} + +/** + * \brief write memory and bypass the cache + * \param[in] ptr memory address + * \param[in] data vaule to be written + */ +Inline void _arc_write_uncached_32(void *ptr, uint32_t data) +{ + Asm("st.di %0, [%1]":: "r"(data), "r"(ptr)); +} + +/** + * \brief read memory with cache + * \param[in] ptr memory address + * \returns value in the memory + */ +Inline uint32_t _arc_read_cached_32(void *ptr) +{ + uint32_t __ret; + Asm("ld %0, [%1]":"=r"(__ret):"r"(ptr)); + return __ret; +} + +/** + * \brief read memory with cache + * \param[in] ptr memory address + * \param[in] data vaule to be written + * \return description + */ +Inline void _arc_write_cached_32(void *ptr, uint32_t data) +{ + Asm("st %0, [%1]":: "r"(data), "r"(ptr)); +} + +/** + * \brief go to main function with proper arguments + * \param argc argument count + * \param argv argument content array + * \retval return value of main function + */ +Inline int32_t _arc_goto_main(int argc, char **argv) { + int __ret; + __asm__ volatile( + "mov %%r0, %1\n" + "mov %%r1, %2\n" + "push_s %%blink\n" + "jl main\n" + "pop_s %%blink\n" + "mov %0, %%r0" + :"=r"(__ret): "r"(argc), "r"(argv)); + return (int)__ret; +} + +#ifdef __cplusplus +} +#endif + +#if defined(LIB_SECURESHIELD) && defined(LIB_SECURESHIELD_OVERRIDES) && (SECURESHIELD_VERSION == 1) +#define OVERRIDE_ARC_HAL_BUILTIN_H +#include "secureshield_overrides.h" +#endif + +/** @} */ +#endif /* _ARC_HAL_BUILTIN_H_ */ +/** @} */ diff --git a/hw/mcu/arc/src/ext/sdk/inc/arc/arc_cache.h b/hw/mcu/arc/src/ext/sdk/inc/arc/arc_cache.h new file mode 100644 index 000000000..dfbc7df9a --- /dev/null +++ b/hw/mcu/arc/src/ext/sdk/inc/arc/arc_cache.h @@ -0,0 +1,321 @@ +/* ------------------------------------------ + * Copyright (c) 2016, Synopsys, Inc. All rights reserved. + + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + + * 1) Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + + * 2) 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. + + * 3) Neither the name of the Synopsys, Inc., nor the names of its contributors may + * be used to endorse or promote products derived from this software without + * specific prior written permission. + + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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. + * + * \version 2016.05 + * \date 2014-07-15 + * \author Wayne Ren(Wei.Ren@synopsys.com) +--------------------------------------------- */ + +/** + * \file + * \ingroup ARC_HAL_MISC_CACHE + * \brief header file of cache module + */ + +#ifndef _ARC_HAL_CACHE_H_ +#define _ARC_HAL_CACHE_H_ + +#include "inc/embARC_toolchain.h" +#include "inc/arc/arc.h" +#include "inc/arc/arc_builtin.h" +#include "inc/arc/arc_exception.h" + +/** + * \name instruction cache control register related definition + * \todo this definitions will be reviewed. + * @{ + */ +#define IC_CTRL_IC_ENABLE 0x0 /*!< enable instruction cache */ +#define IC_CTRL_IC_DISABLE 0x1 /*!< disable instruction cache */ +#define IC_CTRL_DIRECT_ACCESS 0x0 /*!< direct access mode */ +#define IC_CTRL_INDIRECT_ACCESS 0x20 /*!< indirect access mode */ +#define IC_CTRL_OP_SUCCEEDED 0x8 /*!< instruction cache operation succeeded */ +/** @} */ + +/** + * \name data cache control register related definition + * \todo this definition will be reviewed. + * @{ + */ +#define IC_CTRL_I +#define DC_CTRL_DC_ENABLE 0x0 /*!< enable data cache */ +#define DC_CTRL_DC_DISABLE 0x1 /*!< disable data cache */ +#define DC_CTRL_INVALID_ONLY 0x0 /*!< invalid data cache only */ +#define DC_CTRL_INVALID_FLUSH 0x40 /*!< invalid and flush data cache */ +#define DC_CTRL_ENABLE_FLUSH_LOCKED 0x80 /*!< the locked data cache can be flushed */ +#define DC_CTRL_DISABLE_FLUSH_LOCKED 0x0 /*!< the locked data cache cannot be flushed */ +#define DC_CTRL_FLUSH_STATUS 0x100 /*!< flush status */ +#define DC_CTRL_DIRECT_ACCESS 0x0 /*!< direct access mode */ +#define DC_CTRL_INDIRECT_ACCESS 0x20 /*!< indirect access mode */ +#define DC_CTRL_OP_SUCCEEDED 0x4 /*!< data cache operation succeeded */ +/** @} */ + +/** + * \name instruction cache related inline function + * @{ + */ + +/** + * \brief check whether instruction cache is available, + * 0 for not available, >0 for available + */ +Inline uint8_t icache_available(void) +{ + return (_arc_aux_read(AUX_BCR_I_CACHE) & 0xF); +} + +/** + * \brief enable instruction cache + * \param[in] icache_en_mask operation mask + */ +Inline void icache_enable(uint32_t icache_en_mask) +{ + if (!icache_available()) return; + _arc_aux_write(AUX_IC_CTRL, icache_en_mask); +} + +/** + * \brief disable instruction cache + */ +Inline void icache_disable(void) +{ + if (!icache_available()) return; + _arc_aux_write(AUX_IC_CTRL, IC_CTRL_IC_DISABLE); +} + +/** + * \brief invalidate the entire instruction cache + */ +Inline void icache_invalidate(void) +{ + if (!icache_available()) return; + /* invalidate the entire icache */ + _arc_aux_write(AUX_IC_IVIC, 0); + Asm("nop_s"); + Asm("nop_s"); + Asm("nop_s"); +} + +/** + * \brief invalidate specific cache line + * \param[in] address memory address + */ +Inline void icache_invalidate_line(uint32_t address) +{ + if (!icache_available()) return; + _arc_aux_write(AUX_IC_IVIL, address); + /* the 3 nops are required by ARCv2 ISA */ + Asm("nop_s"); + Asm("nop_s"); + Asm("nop_s"); +} + +/** + * \brief lock specific cache line + * \param[in] address memory address + * \return 0, succeeded, -1, failed + */ +Inline int32_t icache_lock_line(uint32_t address) +{ + if (!icache_available()) return -1; + _arc_aux_write(AUX_IC_LIL, address); + if(_arc_aux_read(AUX_IC_CTRL) & IC_CTRL_OP_SUCCEEDED) { + return 0; + } else { + return -1; + } +} + +/** + * \brief set icache access mode + * \param[in] mode, access mode, 1: indirect access 0:direct access + */ +Inline void icache_access_mode(uint32_t mode) +{ + if (!icache_available()) return; + if (mode) { + _arc_aux_write(AUX_IC_CTRL, _arc_aux_read(AUX_IC_CTRL) | IC_CTRL_INDIRECT_ACCESS); + } else { + _arc_aux_write(AUX_IC_CTRL, _arc_aux_read(AUX_IC_CTRL) & (~IC_CTRL_INDIRECT_ACCESS)); + } +} + + +/** @} */ + +/** + * \name data cache related inline functions + * @{ + */ + +/** + * \brief check whether data cache is available, + * 0 for not available, >0 for available + */ +Inline uint8_t dcache_available(void) +{ + return (_arc_aux_read(AUX_BCR_D_CACHE) & 0xF); +} + +/** + * \brief invalidate the entire data cache + */ +Inline void dcache_invalidate(void) +{ + if (!dcache_available()) return; + uint32_t status; + + status = cpu_lock_save(); + _arc_aux_write(AUX_DC_IVDC, 1); + /* wait for flush completion */ + while (_arc_aux_read(AUX_DC_CTRL) & DC_CTRL_FLUSH_STATUS); + cpu_unlock_restore(status); +} + +/** + * \brief invalidate the specific cache line + * \param[in] address memory address + */ +Inline void dcache_invalidate_line(uint32_t address) +{ + if (!dcache_available()) return; + _arc_aux_write(AUX_DC_IVDL, address); + Asm("nop_s"); + Asm("nop_s"); + Asm("nop_s"); +} + +/** + * \brief enable data cache + * \param[in] dcache_en_mask operation mask + */ +Inline void dcache_enable(uint32_t dcache_en_mask) +{ + if (!dcache_available()) return; + _arc_aux_write(AUX_DC_CTRL, dcache_en_mask); +} + +/** + * \brief disable data cache + */ +Inline void dcache_disable(void) +{ + if (!dcache_available()) return; + _arc_aux_write(AUX_DC_CTRL, DC_CTRL_DC_DISABLE); +} + +/** + * \brief flush data cache + */ +Inline void dcache_flush(void) +{ + if (!dcache_available()) return; + uint32_t status; + + status = cpu_lock_save(); + _arc_aux_write(AUX_DC_FLSH, 1); + /* wait for flush completion */ + while (_arc_aux_read(AUX_DC_CTRL) & DC_CTRL_FLUSH_STATUS); + cpu_unlock_restore(status); +} + +/** + * \brief flush the specific data cache line + * \param[in] address memory address + */ +Inline void dcache_flush_line(uint32_t address) +{ + if (!dcache_available()) return; + + uint32_t status; + + status = cpu_lock_save(); + _arc_aux_write(AUX_DC_FLDL, address); + while (_arc_aux_read(AUX_DC_CTRL) & DC_CTRL_FLUSH_STATUS); + cpu_unlock_restore(status); +} + +/** + * \brief lock the specific data cache line + * \param[in] address memory address + * \return 0, succeeded, -1, failed + */ +Inline int dcache_lock_line(uint32_t address) +{ + if (!dcache_available()) return -1; + _arc_aux_write(AUX_DC_LDL, address); + if(_arc_aux_read(AUX_DC_CTRL) & DC_CTRL_OP_SUCCEEDED) { + return 0; + } else { + return -1; + } +} + +/** + * \brief set dcache access mode + * \param[in] mode, access mode, 1: indirect access 0:direct access + */ +Inline void dcache_access_mode(uint32_t mode) +{ + if (!dcache_available()) return; + if (mode) { + _arc_aux_write(AUX_DC_CTRL, _arc_aux_read(AUX_DC_CTRL) | DC_CTRL_INDIRECT_ACCESS); + } else { + _arc_aux_write(AUX_DC_CTRL, _arc_aux_read(AUX_DC_CTRL) & (~DC_CTRL_INDIRECT_ACCESS)); + } +} + +/** @} */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \name declarations of cache related functions + * @{ + */ +extern int32_t icache_invalidate_mlines(uint32_t start_addr, uint32_t size); +extern int32_t icache_lock_mlines(uint32_t start_addr, uint32_t size); +extern int32_t icache_direct_write(uint32_t cache_addr, uint32_t tag, uint32_t data); +extern int32_t icache_direct_read(uint32_t cache_addr, uint32_t *tag, uint32_t *data); +extern int32_t icache_indirect_read(uint32_t mem_addr, uint32_t *tag, uint32_t *data); +extern int32_t dcache_invalidate_mlines(uint32_t start_addr, uint32_t size); +extern int32_t dcache_flush_mlines(uint32_t start_addr, uint32_t size); +extern int32_t dcache_lock_mlines(uint32_t start_addr, uint32_t size); +extern int32_t dcache_direct_write(uint32_t cache_addr, uint32_t tag, uint32_t data); +extern int32_t dcache_direct_read(uint32_t cache_addr, uint32_t *tag, uint32_t *data); +extern int32_t dcache_indirect_read(uint32_t mem_addr, uint32_t *tag, uint32_t *data); +extern void arc_cache_init(void); + +#ifdef __cplusplus +} +#endif + +/** @} */ +#endif /* _ARC_HAL_CACHE_H_ */ diff --git a/hw/mcu/arc/src/ext/sdk/inc/arc/arc_em.h b/hw/mcu/arc/src/ext/sdk/inc/arc/arc_em.h new file mode 100644 index 000000000..cfb963644 --- /dev/null +++ b/hw/mcu/arc/src/ext/sdk/inc/arc/arc_em.h @@ -0,0 +1,133 @@ +/* ------------------------------------------ + * Copyright (c) 2016, Synopsys, Inc. All rights reserved. + + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + + * 1) Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + + * 2) 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. + + * 3) Neither the name of the Synopsys, Inc., nor the names of its contributors may + * be used to endorse or promote products derived from this software without + * specific prior written permission. + + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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. + * + * \version 2016.05 + * \date 2014-06-12 + * \author Wayne Ren(Wei.Ren@synopsys.com) +--------------------------------------------- */ + +/** + * \file + * \ingroup ARC_HAL_CORE_EM + * \brief header file of EM series + */ + +/** + * \addtogroup ARC_HAL_CORE_EM + * @{ + */ + +#ifndef _ARC_HAL_EM_H_ +#define _ARC_HAL_EM_H_ + +#include "inc/arc/arc.h" + +#define AUX_ACC0_LO (0x580) +#define AUX_ACC0_GLO (0x581) +#define AUX_ACC0_HI (0x582) +#define AUX_ACC0_GHI (0x583) +#define AUX_DSP_BFLY0 (0x598) +#define AUX_DSP_FFT_CTRL (0x59e) +#define AUX_DSP_CTRL (0x59f) + +#define AUX_AGU_AUX_AP0 (0x5c0) +#define AUX_AGU_AUX_AP1 (0x5c1) +#define AUX_AGU_AUX_AP2 (0x5c2) +#define AUX_AGU_AUX_AP3 (0x5c3) +#define AUX_AGU_AUX_AP4 (0x5c4) +#define AUX_AGU_AUX_AP5 (0x5c5) +#define AUX_AGU_AUX_AP6 (0x5c6) +#define AUX_AGU_AUX_AP7 (0x5c7) +#define AUX_AGU_AUX_AP8 (0x5c8) +#define AUX_AGU_AUX_AP9 (0x5c9) +#define AUX_AGU_AUX_AP10 (0x5ca) +#define AUX_AGU_AUX_AP11 (0x5cb) +#define AUX_AGU_AUX_AP12 (0x5cc) +#define AUX_AGU_AUX_AP13 (0x5cd) +#define AUX_AGU_AUX_AP14 (0x5ce) +#define AUX_AGU_AUX_AP15 (0x5cf) + +#define AUX_AGU_AXU_OS0 (0x5d0) +#define AUX_AGU_AXU_OS1 (0x5d1) +#define AUX_AGU_AXU_OS2 (0x5d2) +#define AUX_AGU_AXU_OS3 (0x5d3) +#define AUX_AGU_AXU_OS4 (0x5d4) +#define AUX_AGU_AXU_OS5 (0x5d5) +#define AUX_AGU_AXU_OS6 (0x5d6) +#define AUX_AGU_AXU_OS7 (0x5d7) +#define AUX_AGU_AXU_OS8 (0x5d8) +#define AUX_AGU_AXU_OS9 (0x5d9) +#define AUX_AGU_AXU_OS10 (0x5da) +#define AUX_AGU_AXU_OS11 (0x5db) +#define AUX_AGU_AXU_OS12 (0x5dc) +#define AUX_AGU_AXU_OS13 (0x5dd) +#define AUX_AGU_AXU_OS14 (0x5de) +#define AUX_AGU_AXU_OS15 (0x5df) + +#define AUX_AGU_AUX_MOD0 (0x5e0) +#define AUX_AGU_AUX_MOD1 (0x5e1) +#define AUX_AGU_AUX_MOD2 (0x5e2) +#define AUX_AGU_AUX_MOD3 (0x5e3) +#define AUX_AGU_AUX_MOD4 (0x5e4) +#define AUX_AGU_AUX_MOD5 (0x5e5) +#define AUX_AGU_AUX_MOD6 (0x5e6) +#define AUX_AGU_AUX_MOD7 (0x5e7) +#define AUX_AGU_AUX_MOD8 (0x5e8) +#define AUX_AGU_AUX_MOD9 (0x5e9) +#define AUX_AGU_AUX_MOD10 (0x5ea) +#define AUX_AGU_AUX_MOD11 (0x5eb) +#define AUX_AGU_AUX_MOD12 (0x5ec) +#define AUX_AGU_AUX_MOD13 (0x5ed) +#define AUX_AGU_AUX_MOD14 (0x5ee) +#define AUX_AGU_AUX_MOD15 (0x5ef) +#define AUX_AGU_AUX_MOD16 (0x5f0) +#define AUX_AGU_AUX_MOD17 (0x5f1) +#define AUX_AGU_AUX_MOD18 (0x5f2) +#define AUX_AGU_AUX_MOD19 (0x5f3) +#define AUX_AGU_AUX_MOD20 (0x5f4) +#define AUX_AGU_AUX_MOD21 (0x5f5) +#define AUX_AGU_AUX_MOD22 (0x5f6) +#define AUX_AGU_AUX_MOD23 (0x5f7) + +#define AUX_XCCM_BASE (0x5f8) +#define AUX_YCCM_BASE (0x5f9) + + +/** \todo add em series specific definitions here */ + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* _ARC_HAL_EM_H_ */ + +/** @} */ diff --git a/hw/mcu/arc/src/ext/sdk/inc/arc/arc_exception.h b/hw/mcu/arc/src/ext/sdk/inc/arc/arc_exception.h new file mode 100644 index 000000000..d2585ca7f --- /dev/null +++ b/hw/mcu/arc/src/ext/sdk/inc/arc/arc_exception.h @@ -0,0 +1,466 @@ +/* ------------------------------------------ + * Copyright (c) 2016, Synopsys, Inc. All rights reserved. + + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + + * 1) Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + + * 2) 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. + + * 3) Neither the name of the Synopsys, Inc., nor the names of its contributors may + * be used to endorse or promote products derived from this software without + * specific prior written permission. + + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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. + * + * \version 2016.05 + * \date 2014-07-15 + * \author Wayne Ren(Wei.Ren@synopsys.com) +--------------------------------------------- */ + +/** + * \file + * \ingroup ARC_HAL_EXCEPTION_CPU ARC_HAL_EXCEPTION_INTERRUPT + * \brief header file of exception and interrupt management module + */ + +#ifndef _ARC_HAL_EXCEPTION_H_ +#define _ARC_HAL_EXCEPTION_H_ + +#include "inc/embARC_toolchain.h" +#include "inc/arc/arc.h" +#include "inc/arc/arc_builtin.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \addtogroup ARC_HAL_EXCEPTION_CPU + * @{ + * \todo need a conf.h from application or board to define the + * features of processor, such as number of exception, code + * density and FIQ. + */ +#ifndef NUM_EXC_CPU +#define NUM_EXC_CPU 16 /*!< number of CPU exceptions */ +#endif + +#ifndef NUM_EXC_INT +#define NUM_EXC_INT 9 /*!< number of interrupt exceptions, defined by users*/ +#endif + +#define NUM_EXC_ALL (NUM_EXC_CPU + NUM_EXC_INT) /*!< total number of exceptions */ + + + +#ifdef ARC_FEATURE_SEC_PRESENT +typedef struct int_exc_frame { + uint32_t erbta; + + uint32_t r30; /* r30 is useless, skipped? */ + uint32_t ilink; /* r29 is useless, skipped?*/ + /* r28 is sp, saved other place */ + uint32_t fp; /* r27 */ + uint32_t gp; /* r26 */ + + uint32_t r12; + + uint32_t lp_end, lp_start, lp_count; + +#ifdef ARC_FEATURE_CODE_DENSITY + uint32_t ei, ldi, jli; +#endif + + uint32_t r0, r1, r2, r3; +#ifndef ARC_FEATURE_RF16 + uint32_t r4, r5, r6, r7, r8, r9; +#endif + uint32_t r10, r11; + + uint32_t blink; /* r31 */ + uint32_t ret; + uint32_t sec_stat; + uint32_t status32; +} EMBARC_PACKED INT_EXC_FRAME; +#else +typedef struct int_exc_frame { + uint32_t erbta; + + uint32_t r30; /* r30 is useless, skipped? */ + uint32_t ilink; /* r29 is useless, skipped?*/ + /* r28 is sp, saved other place */ + uint32_t fp; /* r27 */ + uint32_t gp; /* r26 */ + + uint32_t r12; + + uint32_t r0, r1, r2, r3; +#ifndef ARC_FEATURE_RF16 + uint32_t r4, r5, r6, r7, r8, r9; +#endif + uint32_t r10, r11; + + uint32_t blink; /* r31 */ + + uint32_t lp_end, lp_start, lp_count; + +#ifdef ARC_FEATURE_CODE_DENSITY + uint32_t ei, ldi, jli; +#endif + + uint32_t ret; + uint32_t status32; +} EMBARC_PACKED INT_EXC_FRAME; +#endif + +typedef struct callee_frame { +#ifndef ARC_FEATURE_RF16 + uint32_t r25; + uint32_t r24; + uint32_t r23; + uint32_t r22; + uint32_t r21; + uint32_t r20; + uint32_t r19; + uint32_t r18; + uint32_t r17; + uint32_t r16; +#endif + uint32_t r15; + uint32_t r14; + uint32_t r13; +} EMBARC_PACKED CALLEE_FRAME; + +typedef struct processor_frame { + CALLEE_FRAME callee_regs; + INT_EXC_FRAME exc_frame; +} EMBARC_PACKED PROCESSOR_FRAME; + +#define ARC_PROCESSOR_FRAME_SIZE (sizeof(PROCESSOR_FRAME) / sizeof(uint32_t)) +#define ARC_EXC_FRAME_SIZE (sizeof(INT_EXC_FRAME) / sizeof(uint32_t)) +#define ARC_CALLEE_FRAME_SIZE (sizeof(CALLEE_FRAME) / sizeof(uint32_t)) + + +extern uint32_t exc_nest_count; + +/** + * \brief write the exception vector base + * + * \param[in] vec_base the target vector base + */ +Inline void arc_vector_base_write(const void * vec_base) +{ + _arc_aux_write(AUX_INT_VECT_BASE, (uint32_t)vec_base); +} + +/** + * \brief read current exception vector base + * + * \returns exception vector base (uint32_t) + */ +Inline uint32_t arc_vector_base_read(void) +{ + return _arc_aux_read(AUX_INT_VECT_BASE); +} + +/** + * \brief sense whether in exc/interrupt processing + * + * \retval 0 not in exc/interrupt processing + * \retval 1 in exc/interrupt processing + */ +Inline uint32_t exc_sense(void) +{ + return (exc_nest_count > 0U); +} + +/** @}*/ + +/** + * \addtogroup ARC_HAL_EXCEPTION_INTERRUPT + * @{ + */ +#ifndef INT_PRI_MIN +#define INT_PRI_MIN (-2) /*!< the minimum interrupt priority */ +#endif + +#define INT_PRI_MAX (-1) /*!< the maximum interrupt priority */ +/** + * \brief disable the specific interrupt + * + * \param[in] intno interrupt number + */ +Inline void arc_int_disable(const uint32_t intno) +{ + _arc_aux_write(AUX_IRQ_SELECT, intno); + _arc_aux_write(AUX_IRQ_ENABLE, 0); +} + +/** + * \brief enable the specific int + * + * \param[in] intno interrupt number + */ +Inline void arc_int_enable(const uint32_t intno) +{ + _arc_aux_write(AUX_IRQ_SELECT, intno); + _arc_aux_write(AUX_IRQ_ENABLE, 1); +} + +/** + * \brief check whether the specific int is enabled + * + * \param[in] intno interrupt number + * \return 0 disabled, 1 enabled + */ +Inline uint32_t arc_int_enabled(const uint32_t intno) +{ + _arc_aux_write(AUX_IRQ_SELECT, intno); + return _arc_aux_read(AUX_IRQ_ENABLE); +} + +/** + * \brief get the interrupt priority mask + * + * \returns interrupt priority mask, negative num + */ +Inline uint32_t arc_int_ipm_get(void) +{ + return ((_arc_aux_read(AUX_STATUS32) >> 1) & 0x0f); +} + +/** + * \brief set the interrupt priority mask + * + * \param[in] intpri interrupt priority + */ +Inline void arc_int_ipm_set(uint32_t intpri) +{ + volatile uint32_t status; + status = _arc_aux_read(AUX_STATUS32) & ~0x1e; + + status = status | ((intpri << 1) & 0x1e); + /* sr cannot write AUX_STATUS32 */ + Asm("kflag %0"::"ir"(status)); +} + +/** + * \brief get current interrupt priority mask + * + * \param[in] intno interrupt number + */ +Inline uint32_t arc_int_pri_get(const uint32_t intno) +{ + _arc_aux_write(AUX_IRQ_SELECT, intno); + return _arc_aux_read(AUX_IRQ_PRIORITY); +} + +/** + * \brief set interrupt priority + * + * \param[in] intno interrupt number + * \param[in] intpri interrupt priority + */ +Inline void arc_int_pri_set(const uint32_t intno, uint32_t intpri) +{ + _arc_aux_write(AUX_IRQ_SELECT, intno); + _arc_aux_write(AUX_IRQ_PRIORITY, intpri | (_arc_aux_read(AUX_IRQ_PRIORITY) & 0xfffffff0)); +} + +/** + * \brief set interrupt secure or not secure + * + * \param[in] intno interrupt number + * \param[in] secure, 0 for normal, >0 for secure + */ +Inline void arc_int_secure_set(const uint32_t intno, uint32_t secure) +{ + + _arc_aux_write(AUX_IRQ_SELECT, intno); + + if (secure) { + _arc_aux_write(AUX_IRQ_PRIORITY, _arc_aux_read(AUX_IRQ_PRIORITY) | + (1 << AUX_IRQ_PRIORITY_BIT_S)); + } else { + _arc_aux_write(AUX_IRQ_PRIORITY, _arc_aux_read(AUX_IRQ_PRIORITY) & 0xf); + } + +} + +/** + * \brief probe the pending status of interrupt + * + * \param[in] intno interrupt number + * + * \returns 1 pending, 0 no pending + */ +Inline uint32_t arc_int_probe(const uint32_t intno) +{ + _arc_aux_write(AUX_IRQ_SELECT, intno); + return _arc_aux_read(AUX_IRQ_PENDING); +} + +/** + * \brief trigger the interrupt in software + * + * \param[in] intno interrupt number + */ +Inline void arc_int_sw_trigger(const uint32_t intno) +{ + _arc_aux_write(AUX_IRQ_HINT, intno); +} + +/** + * \brief config the interrupt level triggered or pulse triggered + * + * \param[in] intno interrupt number + * \param[in] level, 0-level trigger, 1-pluse triggered + */ +Inline void arc_int_level_config(const uint32_t intno, const uint32_t level) +{ + _arc_aux_write(AUX_IRQ_SELECT, intno); + _arc_aux_write(AUX_IRQ_TRIGGER, level); +} + +/** + * \brief lock cpu, disable interrupts + */ +Inline void arc_lock(void) +{ + Asm("clri"); + Asm("":::"memory"); +} + +/** + * \brief unlock cpu, enable interrupts to happen + */ +Inline void arc_unlock(void) +{ + Asm("":::"memory"); + Asm("seti"); +} + +/** + * \brief lock cpu and staus + * + * \returns cpu status + */ +Inline uint32_t arc_lock_save(void) +{ + return _arc_clri(); +} + +/** + * \brief unlock cpu with the specific status + * + * \param[in] status cpu status saved by cpu_lock_save + */ +Inline void arc_unlock_restore(const uint32_t status) +{ + _arc_seti(status); +} +/** @}*/ + +/** + * \addtogroup ARC_HAL_EXCEPTION_CPU + * @{ + */ +/** + * \typedef EXC_ENTRY + * \brief the data type for exception entry + */ +typedef void (*EXC_ENTRY) (void); +/** + * \typedef EXC_HANDLER + * \brief the data type for exception handler + */ +typedef void (*EXC_HANDLER) (void *exc_frame); +/** @}*/ + + +/** + * \ingroup ARC_HAL_EXCEPTION_INTERRUPT + * \typedef INT_HANDLER + * \brief the data type for interrupt handler + */ +typedef void (*INT_HANDLER) (void *ptr); + +extern EXC_ENTRY exc_entry_table[NUM_EXC_ALL]; +extern EXC_HANDLER exc_int_handler_table[NUM_EXC_ALL]; + +/** \ingroup ARC_HAL_EXCEPTION_CPU + * @{ + */ +/** + * \fn _arc_reset + * \brief the reset entry + */ +extern void _arc_reset(void); +/** + * \fn exc_entry_cpu + * \brief the default CPU exception entry + */ +extern void exc_entry_cpu(void); + +/** + * \fn exc_entry_firq + * \brief the fast interrupt exception entry + */ +extern void exc_entry_firq(void); +/** + * \fn exc_entry_int + * \brief the interrupt exception entry + */ +extern void exc_entry_int(void); +/** @}*/ + +/* excetpion related apis */ +extern void exc_int_init(void); +extern int32_t exc_entry_install(const uint32_t excno, EXC_ENTRY entry); +extern EXC_ENTRY exc_entry_get(const uint32_t excno); +extern int32_t exc_handler_install(const uint32_t excno, EXC_HANDLER handler); +extern EXC_HANDLER exc_handler_get(const uint32_t excno); + +/* interrupt related apis */ +extern int32_t int_disable(const uint32_t intno); +extern int32_t int_enable(const uint32_t intno); +extern int32_t int_enabled(const uint32_t intno); +extern int32_t int_ipm_get(void); +extern int32_t int_ipm_set(int32_t intpri); +extern int32_t int_pri_get(const uint32_t intno); +extern int32_t int_pri_set(const uint32_t intno, int32_t intpri); +extern int32_t int_probe(const uint32_t intno); +extern int32_t int_sw_trigger(const uint32_t intno); +extern int32_t int_level_config(const uint32_t intno, const uint32_t level); +extern void cpu_lock(void); +extern void cpu_unlock(void); +extern uint32_t cpu_lock_save(void); +extern void cpu_unlock_restore(const uint32_t status); +extern int32_t int_handler_install(const uint32_t intno, INT_HANDLER handler); +extern INT_HANDLER int_handler_get(const uint32_t intno); +extern int32_t int_secure_set(const uint32_t intno, uint32_t secure); + +#ifdef __cplusplus +} +#endif + +#if defined(LIB_SECURESHIELD) && defined(LIB_SECURESHIELD_OVERRIDES) && (SECURESHIELD_VERSION == 1) +#define OVERRIDE_ARC_HAL_EXCEPTION_H +#include "secureshield_overrides.h" +#endif + +#endif /* _ARC_HAL_EXCEPTION_H_*/ diff --git a/hw/mcu/arc/src/ext/sdk/inc/arc/arc_feature_config.h b/hw/mcu/arc/src/ext/sdk/inc/arc/arc_feature_config.h new file mode 100644 index 000000000..87b1913df --- /dev/null +++ b/hw/mcu/arc/src/ext/sdk/inc/arc/arc_feature_config.h @@ -0,0 +1,397 @@ +/* ------------------------------------------ + * Copyright (c) 2016, Synopsys, Inc. All rights reserved. + + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + + * 1) Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + + * 2) 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. + + * 3) Neither the name of the Synopsys, Inc., nor the names of its contributors may + * be used to endorse or promote products derived from this software without + * specific prior written permission. + + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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. + * + * \version 2016.05 + * \date 2016-09-08 + * \author Huaqi Fang(Huaqi.Fang@synopsys.com) +--------------------------------------------- */ + +/** + * \file + * \ingroup ARC_HAL_MISC + * \brief header file for arc feature configuration + */ + +/** + * \addtogroup ARC_HAL_MISC + * @{ + */ + +#ifndef _ARC_FEATURE_CONFIG_H_ +#define _ARC_FEATURE_CONFIG_H_ + +// Enable core_config.h in EMSK OSP +//#ifdef EMBARC_TCF_GENERATED +#include "arc_core_config.h" +//#endif + +/** ARC baseline instruction set version number */ +#if !defined(_ARCVER) +#if defined(core_config_cir_identity_arcver) +#define _ARCVER core_config_cir_identity_arcver +#else +#define _ARCVER 0x42 +#endif +#endif + +/** ARC CPU Clock Frequency in Hz unit */ +#if !defined(ARC_FEATURE_CPU_CLOCK_FREQ) +#if defined(core_config_clock_speed) +#define ARC_FEATURE_CPU_CLOCK_FREQ (core_config_clock_speed*1000000) +#endif +#endif + +/** ARC PC size */ +#if !defined(ARC_FEATURE_PC_SIZE) +#if defined(core_config_pc_size) +#define ARC_FEATURE_PC_SIZE core_config_pc_size +#else +#define ARC_FEATURE_PC_SIZE 32 +#endif +#endif + +/** ARC LPC size */ +#if !defined(ARC_FEATURE_LPC_SIZE) +#if defined(core_config_lpc_size) +#define ARC_FEATURE_LPC_SIZE core_config_lpc_size +#else +#define ARC_FEATURE_LPC_SIZE 32 +#endif +#endif + +/** ARC Addr size */ +#if !defined(ARC_FEATURE_ADDR_SIZE) +#if defined(core_config_addr_size) +#define ARC_FEATURE_ADDR_SIZE core_config_addr_size +#else +#define ARC_FEATURE_ADDR_SIZE 32 +#endif +#endif + +/** ARC Endian/Byte Order */ +#define ARC_FEATURE_LITTLE_ENDIAN 1234 +#define ARC_FEATURE_BIG_ENDIAN 4321 + +#if !defined(ARC_FEATURE_BYTE_ORDER) +#if defined(core_config_bcr_isa_config_b) +#if core_config_bcr_isa_config_b == 0 +#define ARC_FEATURE_BYTE_ORDER ARC_FEATURE_LITTLE_ENDIAN +#else +#define ARC_FEATURE_BYTE_ORDER ARC_FEATURE_BIG_ENDIAN +#endif +#else +#define ARC_FEATURE_BYTE_ORDER ARC_FEATURE_LITTLE_ENDIAN +#endif +#endif + +/** Reduced register option, if enabled, ARC_FEATURE_RF16 will be defined */ +#if !defined(ARC_FEATURE_RF16) +#if defined(core_config_bcr_rf_build_e) && core_config_bcr_rf_build_e == 1 +#define ARC_FEATURE_RF16 +#endif +#endif + +/** Unaligned access option, if enabled, ARC_FEATURE_UNALIGNED will be defined */ +#if !defined(ARC_FEATURE_UNALIGNED) +#if defined(core_config_unaligned) && core_config_unaligned == 1 +#define ARC_FEATURE_UNALIGNED +#endif +#endif + + +/** Code density option, if enabled, ARC_FEATURE_CODE_DENSITY will be defined */ +#if !defined(ARC_FEATURE_CODE_DENSITY) +#if defined(core_config_code_density) && core_config_code_density == 1 +#define ARC_FEATURE_CODE_DENSITY +#endif +#endif + +/** The number of register file banks */ +#if !defined(ARC_FEATURE_RGF_NUM_BANKS) +#if defined(core_config_rgf_num_banks) +#define ARC_FEATURE_RGF_NUM_BANKS core_config_rgf_num_banks +#else +#define ARC_FEATURE_RGF_NUM_BANKS 1 +#endif +#endif + +/** The number of registers replicated per register bank */ +#if !defined(ARC_FEATURE_RGF_BANKED_REGS) +#if defined(core_config_rgf_banked_regs) +#define ARC_FEATURE_RGF_BANKED_REGS core_config_rgf_banked_regs +#endif +#endif + +/** Interrupt unit presence */ +#if !defined(ARC_FEATURE_INTERRUPTS_PRESENT) +#if defined(core_config_interrupts_present) +#define ARC_FEATURE_INTERRUPTS_PRESENT core_config_interrupts_present +#endif +#endif + +/** FIRQ_OPTION configuration option, 1 for enabled, 0 for disabled */ +#if !defined(ARC_FEATURE_FIRQ) +#if defined(core_config_bcr_irq_build_f) +#define ARC_FEATURE_FIRQ core_config_bcr_irq_build_f +#else +#define ARC_FEATURE_FIRQ 0 +#endif +#endif + +/** The number of interrupts */ +#if !defined(NUM_EXC_INT) +#if defined(core_config_interrupts_number) +#define NUM_EXC_INT core_config_interrupts_number +#endif +#endif + +/** The number of external interrupts */ +#if !defined(NUM_EXC_EXT_INT) +#if defined(core_config_interrupts_externals) +#define NUM_EXC_EXT_INT core_config_interrupts_externals +#endif +#endif + +/** The interrupt priority levels */ +#if !defined(INT_PRI_MIN) +#if defined(core_config_interrupts_priorities) +#define INT_PRI_MIN (-core_config_interrupts_priorities) +#endif +#endif + +// ARC TIMER_BUILD +/** Timer0 present or not */ +#if !defined(ARC_FEATURE_TIMER0_PRESENT) +#if defined(core_config_timer0) +#define ARC_FEATURE_TIMER0_PRESENT core_config_timer0 +#define ARC_FEATURE_TIMER0_LEVEL (core_config_timer0_level-core_config_interrupts_priorities) +#define ARC_FEATURE_TIMER0_VECTOR core_config_timer0_vector +#endif +#endif + +/** Timer1 present or not */ +#if !defined(ARC_FEATURE_TIMER1_PRESENT) +#if defined(core_config_timer1) +#define ARC_FEATURE_TIMER1_PRESENT core_config_timer1 +#define ARC_FEATURE_TIMER1_LEVEL (core_config_timer1_level-core_config_interrupts_priorities) +#define ARC_FEATURE_TIMER1_VECTOR core_config_timer1_vector +#endif +#endif + +/** Secure Timer0 present or not */ +#if !defined(ARC_FEATURE_SEC_TIMER0_PRESENT) +#if defined(core_config_sec_timer0) +#define ARC_FEATURE_SEC_TIMER0_PRESENT core_config_sec_timer0 +#define ARC_FEATURE_SEC_TIMER0_LEVEL (core_config_sec_timer0_level-core_config_interrupts_priorities) +#define ARC_FEATURE_SEC_TIMER0_VECTOR 20 +#endif +#endif + +/** Secure Timer1 present or not */ +#if !defined(ARC_FEATURE_SEC_TIMER1_PRESENT) +#if defined(core_config_sec_timer1) +#define ARC_FEATURE_SEC_TIMER1_PRESENT core_config_sec_timer1 +#define ARC_FEATURE_SEC_TIMER1_LEVEL (core_config_sec_timer1_level-core_config_interrupts_priorities) +#define ARC_FEATURE_SEC_TIMER1_VECTOR 21 +#endif +#endif + + +/** 64bit RTC present or not */ +#if !defined(ARC_FEATURE_RTC_PRESENT) +#if defined(core_config_rtc) +#define ARC_FEATURE_RTC_PRESENT core_config_rtc +#endif +#endif + +// Memory related definitions +/** ICCM Presence, base address and size */ +#if !defined(ARC_FEATURE_ICCM_PRESENT) +#if defined(core_config_iccm_present) && core_config_iccm_present == 1 +#define ARC_FEATURE_ICCM_PRESENT 1 +#define ARC_FEATURE_ICCM_BASE core_config_iccm_base +#define ARC_FEATURE_ICCM_SIZE core_config_iccm_size +#endif +#endif + +/** ICCM0 Presence, base address and size */ +#if !defined(ARC_FEATURE_ICCM0_PRESENT) +#if defined(core_config_iccm0_present) && core_config_iccm0_present == 1 +#define ARC_FEATURE_ICCM0_PRESENT 1 +#define ARC_FEATURE_ICCM0_BASE core_config_iccm0_base +#define ARC_FEATURE_ICCM0_SIZE core_config_iccm0_size +#endif +#endif + +/** ICCM1 Presence, base address and size */ +#if !defined(ARC_FEATURE_ICCM1_PRESENT) +#if defined(core_config_iccm1_present) && core_config_iccm1_present == 1 +#define ARC_FEATURE_ICCM1_PRESENT 1 +#define ARC_FEATURE_ICCM1_BASE core_config_iccm1_base +#define ARC_FEATURE_ICCM1_SIZE core_config_iccm1_size +#endif +#endif + +/** DCCM Presence, base address and size */ +#if !defined(ARC_FEATURE_DCCM_PRESENT) +#if defined(core_config_dccm_present) && core_config_dccm_present == 1 +#define ARC_FEATURE_DCCM_PRESENT 1 +#define ARC_FEATURE_DCCM_BASE core_config_dccm_base +#define ARC_FEATURE_DCCM_SIZE core_config_dccm_size +#ifdef core_config_dccm_interleave +#define ARC_FEATURE_DCCM_INTERLEAVE core_config_dccm_interleave +#endif +#endif +#endif + +/** Peripheral memory region(DMP) base address, if dmp configured, this macro will be defined as base address */ +#if !defined(ARC_FEATURE_DMP_PERIPHERAL) +#if defined(core_config_cir_dmp_peripheral) +#define ARC_FEATURE_DMP_PERIPHERAL core_config_cir_dmp_peripheral +#endif +#endif + +/** MPU options */ +#if !defined(ARC_FEATURE_MPU_PRESENT) +#if defined(core_config_mpu_present) && core_config_mpu_present == 1 +#define ARC_FEATURE_MPU_PRESENT 1 +#define ARC_FEATURE_MPU_VERSION core_config_bcr_mpu_build_version +#define ARC_FEATURE_MPU_REGIONS core_config_mpu_regions +#ifdef core_config_bcr_mpu_build_i +#define ARC_FEATURE_MPU_BUILD_I core_config_bcr_mpu_build_i +#endif +#ifdef core_config_bcr_mpu_build_s +#define ARC_FEATURE_MPU_BUILD_S core_config_bcr_mpu_build_s +#endif +#endif +#endif + +/** Secure BCR SEC_BUILD BCR */ +#if !defined(ARC_FEATURE_SEC_PRESENT) +#if defined(core_config_bcr_sec_build) +#define ARC_FEATURE_SEC_PRESENT 1 +#define ARC_FEATURE_SEC_VERSION core_config_bcr_sec_build_version +#define ARC_FEATURE_SEC_BUILD_DSM core_config_bcr_sec_build_dsm +#define ARC_FEATURE_SEC_BUILD_NSM core_config_bcr_sec_build_nsm +#define ARC_FEATURE_SEC_BUILD_I1SM core_config_bcr_sec_build_i1sm +#define ARC_FEATURE_SEC_BUILD_I0SM core_config_bcr_sec_build_i0sm +#define ARC_FEATURE_SEC_BUILD_S core_config_bcr_sec_build_s +#define ARC_FEATURE_SEC_BUILD_EI core_config_bcr_sec_build_ei +#define ARC_FEATURE_SEC_BUILD_ED core_config_bcr_sec_build_ed +#endif +#endif + +#if !defined(ARC_FEATURE_SEC_MODES) +#if defined(core_config_sec_modes) +#define ARC_FEATURE_SEC_MODES core_config_sec_modes +#endif +#endif + +/** Data Cache options */ +#if !defined(ARC_FEATURE_DCACHE_PRESENT) +#if defined(core_config_dcache_present) && core_config_dcache_present == 1 +#define ARC_FEATURE_DCACHE_PRESENT 1 +#define ARC_FEATURE_DCACHE_BUILD core_config_bcr_d_cache_build +#define ARC_FEATURE_DCACHE_BUILD_VERSION core_config_bcr_d_cache_build_version +#define ARC_FEATURE_DCACHE_BUILD_ASSOC core_config_bcr_d_cache_build_assoc +#define ARC_FEATURE_DCACHE_BUILD_CAPACITY core_config_bcr_d_cache_build_capacity +#define ARC_FEATURE_DCACHE_BUILD_BSIZE core_config_bcr_d_cache_build_bsize +#define ARC_FEATURE_DCACHE_BUILD_FL core_config_bcr_d_cache_build_fl +#define ARC_FEATURE_DCACHE_BUILD_U core_config_bcr_d_cache_build_u +#define ARC_FEATURE_DCACHE_SIZE core_config_dcache_size +#define ARC_FEATURE_DCACHE_LINE_SIZE core_config_dcache_line_size +#define ARC_FEATURE_DCACHE_WAYS core_config_dcache_ways +#define ARC_FEATURE_DCACHE_FEATURE core_config_dcache_feature +#endif +#endif + +/** Instruction Cache options */ +#if !defined(ARC_FEATURE_ICACHE_PRESENT) +#if defined(core_config_icache_present) && core_config_icache_present == 1 +#define ARC_FEATURE_ICACHE_PRESENT 1 +#define ARC_FEATURE_ICACHE_BUILD core_config_bcr_i_cache_build +#define ARC_FEATURE_ICACHE_BUILD_VERSION core_config_bcr_i_cache_build_version +#define ARC_FEATURE_ICACHE_BUILD_ASSOC core_config_bcr_i_cache_build_assoc +#define ARC_FEATURE_ICACHE_BUILD_CAPACITY core_config_bcr_i_cache_build_capacity +#define ARC_FEATURE_ICACHE_BUILD_BSIZE core_config_bcr_i_cache_build_bsize +#define ARC_FEATURE_ICACHE_BUILD_FL core_config_bcr_i_cache_build_fl +#define ARC_FEATURE_ICACHE_BUILD_D core_config_bcr_i_cache_build_d +#define ARC_FEATURE_ICACHE_SIZE core_config_icache_size +#define ARC_FEATURE_ICACHE_LINE_SIZE core_config_icache_line_size +#define ARC_FEATURE_ICACHE_WAYS core_config_icache_ways +#define ARC_FEATURE_ICACHE_FEATURE core_config_icache_feature +#endif +#endif + +/** ARC uDMA options */ +#if !defined(ARC_FEATURE_DMAC) +#if defined(core_config_dmac) +#define ARC_FEATURE_DMAC core_config_dmac +#define CORE_DMAC_CHANNELS core_config_dmac_channels +#define CORE_DMAC_REGISTERS core_config_dmac_registers +#if core_config_bcr_dmac_build_int_cfg == 2 && core_config_bcr_dmac_build_int_cfg == 4 +#define DMA_MULTI_IRQ 1 +#else +#define DMA_MULTI_IRQ 0 +#endif +#define ARC_FEATURE_DMAC_PRESENT core_config_dmac +#define ARC_FEATURE_DMAC_VERSION core_config_bcr_dmac_build_version +#define ARC_FEATURE_DMAC_CHANNELS core_config_dmac_channels +#define ARC_FEATURE_DMAC_REGISTERS core_config_dmac_registers +#define ARC_FEATURE_DMAC_INT_CFG core_config_bcr_dmac_build_int_cfg +#define ARC_FEATURE_DMAC_FIFO_DEPTH core_config_dmac_fifo_depth + +#ifdef ARC_FEATURE_SEC_TIMER0_PRESENT +#define DMA_IRQ_NUM_START 22 +#define ARC_FEATURE_DMAC_VECTOR_START 22 +#else +#define DMA_IRQ_NUM_START 20 +#define ARC_FEATURE_DMAC_VECTOR_START 20 +#endif + +#endif +#endif + + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef ARC_FEATURE_UNALIGNED +#define STATUS32_RESET_VALUE (1<<19) +#else +#define STATUS32_RESET_VALUE (0) +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* _ARC_FEATURE_CONFIG_H_ */ + +/** @} */ diff --git a/hw/mcu/arc/src/ext/sdk/inc/arc/arc_timer.h b/hw/mcu/arc/src/ext/sdk/inc/arc/arc_timer.h new file mode 100644 index 000000000..b5237f31a --- /dev/null +++ b/hw/mcu/arc/src/ext/sdk/inc/arc/arc_timer.h @@ -0,0 +1,99 @@ +/* ------------------------------------------ + * Copyright (c) 2016, Synopsys, Inc. All rights reserved. + + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + + * 1) Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + + * 2) 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. + + * 3) Neither the name of the Synopsys, Inc., nor the names of its contributors may + * be used to endorse or promote products derived from this software without + * specific prior written permission. + + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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. + * + * \version 2016.05 + * \date 2014-07-15 + * \author Wayne Ren(Wei.Ren@synopsys.com) +--------------------------------------------- */ + +/** + * \file + * \ingroup ARC_HAL_MISC_TIMER + * \brief header file of ARC internal timer + */ + +/** + * \addtogroup ARC_HAL_MISC_TIMER + * @{ + */ + +#ifndef _ARC_HAL_TIMER_H_ +#define _ARC_HAL_TIMER_H_ +#include "inc/arc/arc.h" +#include "inc/embARC_toolchain.h" + +/** + * \name arc internal timers names + * @{ + */ +#define TIMER_0 0 /*!< macro name for arc internal timer 0 */ +#define TIMER_1 1 /*!< macro name for arc internal timer 1 */ +#define TIMER_RTC 2 /*!< macro name for arc internal RTC */ + +/** @} */ + +/** + * \name bit definition of RTC CTRL reg + * @{ + */ + +#define TIMER_RTC_ENABLE 0x01 /*!< enable RTC */ +#define TIMER_RTC_CLEAR 0x02 /* clears the AUX_RTC_LOW and AUX_RTC_HIGH */ +#define TIMER_RTC_STATUS_A0 0x40000000 /*!< track bit of atomicity of reads of RTC */ +#define TIMER_RTC_STATUS_A1 0x80000000 /*!< track bit of atomicity of reads of RTC */ + +/** @} */ + +/** + * \name bit definition of timer CTRL reg + * @{ + */ +#define TIMER_CTRL_IE (1 << 0) /*!< Interrupt when count reaches limit */ +#define TIMER_CTRL_NH (1 << 1) /*!< Count only when CPU NOT halted */ +#define TIMER_CTRL_W (1 << 2) /*!< watchdog enable */ +#define TIMER_CTRL_IP (1 << 3) /*!< interrupt pending */ + +/** @} */ + +#ifdef __cplusplus +extern "C" { +#endif + +extern int32_t arc_timer_present(const uint32_t no); +extern int32_t arc_timer_start(const uint32_t no, const uint32_t mode, const uint32_t val); +extern int32_t arc_timer_stop(const uint32_t no); +extern int32_t arc_timer_current(const uint32_t no, void* val); +extern int32_t arc_timer_int_clear(const uint32_t no); +extern void arc_timer_init(void); + +#ifdef __cplusplus +} +#endif + +#endif /* _ARC_HAL_TIMER_H_ */ +/** }@*/ diff --git a/hw/mcu/arc/src/ext/sdk/inc/embARC_debug.h b/hw/mcu/arc/src/ext/sdk/inc/embARC_debug.h new file mode 100644 index 000000000..092374622 --- /dev/null +++ b/hw/mcu/arc/src/ext/sdk/inc/embARC_debug.h @@ -0,0 +1,94 @@ +/* ------------------------------------------ + * Copyright (c) 2017, Synopsys, Inc. All rights reserved. + + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + + * 1) Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + + * 2) 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. + + * 3) Neither the name of the Synopsys, Inc., nor the names of its contributors may + * be used to endorse or promote products derived from this software without + * specific prior written permission. + + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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. + * + * \version 2017.03 + * \date 2014-12-26 + * \author Wayne Ren(Wei.Ren@synopsys.com) +--------------------------------------------- */ + +/** + * \file + * \ingroup EMBARC_DEBUG + * \brief necessary definitions of debug + */ + +#ifndef _EMBARC_DEBUG_H_ +#define _EMBARC_DEBUG_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef EMBARC_PRINTF + #include "common/xprintf.h" + #define EMBARC_PRINTF xprintf +#endif + +/* + * if you want to use DBG or dbg_printf, + * please define DEBUG or DBG_LESS or DBG_MORE before include embARC_debug.h + * DEBUG: enable debug print + * DBG_LESS: enable less debug msg + * DBG_MORE: enable more debug msg + **/ + +#if defined(DEBUG) +#if defined(DEBUG_HOSTLINK) +#include +#define DBG(fmt, ...) printf(fmt, ##__VA_ARGS__) +#else +#define DBG(fmt, ...) EMBARC_PRINTF(fmt, ##__VA_ARGS__) +#endif +#else +#define DBG(fmt, ...) +#endif + +#define DBG_LESS_INFO 0x01 /* less debug messages */ +#define DBG_MORE_INFO 0x02 /* more debug messages */ + + +#if defined (DBG_LESS) +#define DBG_TYPE (DBG_LESS_INFO) +#elif defined (DBG_MORE) +#define DBG_TYPE ((DBG_LESS_INFO) | (DBG_MORE_INFO)) +#else +#define DBG_TYPE 0 +#endif + +#if DBG_TYPE > 0 +#define dbg_printf(type, fmt, ...) \ + if (((type) & DBG_TYPE)) { EMBARC_PRINTF(fmt, ##__VA_ARGS__); } +#else +#define dbg_printf(type, fmt, ...) +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* DEBUG_H_ */ diff --git a/hw/mcu/arc/src/ext/sdk/inc/embARC_error.h b/hw/mcu/arc/src/ext/sdk/inc/embARC_error.h new file mode 100644 index 000000000..9bd9c318a --- /dev/null +++ b/hw/mcu/arc/src/ext/sdk/inc/embARC_error.h @@ -0,0 +1,156 @@ +/* ------------------------------------------ + * Copyright (c) 2016, Synopsys, Inc. All rights reserved. + + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + + * 1) Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + + * 2) 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. + + * 3) Neither the name of the Synopsys, Inc., nor the names of its contributors may + * be used to endorse or promote products derived from this software without + * specific prior written permission. + + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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. + * + * \version 2016.05 + * \date 2014-12-25 + * \author Wayne Ren(Wei.Ren@synopsys.com) +--------------------------------------------- */ + +/** + * \file + * \ingroup EMBARC_ERROR + * \brief header file to define common definitions error management + */ + +/** + * \addtogroup EMBARC_ERROR + * @{ + */ + +#ifndef _EMBARC_ERROR_H_ +#define _EMBARC_ERROR_H_ + +#include +#include "inc/arc/arc_builtin.h" + +#ifdef __cplusplus +extern "C" { +#endif +/** + * \name Main Error Code Definitions + * @{ + */ +#define E_OK (0) /*!< ok */ +#define E_SYS (-5) /*!< system error */ +#define E_NOSPT (-9) /*!< unsupported features */ +#define E_RSFN (-10) /*!< reserved function code */ +#define E_RSATR (-11) /*!< reserved attribute */ +#define E_PAR (-17) /*!< parameter error */ +#define E_ID (-18) /*!< invalid ID number */ +#define E_CTX (-25) /*!< context error */ +#define E_MACV (-26) /*!< memory access violation */ +#define E_OACV (-27) /*!< object access violation */ +#define E_ILUSE (-28) /*!< illegal service call use */ +#define E_NOMEM (-33) /*!< insufficient memory */ +#define E_NOID (-34) /*!< no ID number available */ +#define E_NORES (-35) /*!< no resource available */ +#define E_OBJ (-41) /*!< object state error */ +#define E_NOEXS (-42) /*!< non-existent object */ +#define E_QOVR (-43) /*!< queue overflow */ +#define E_RLWAI (-49) /*!< forced release from waiting */ +#define E_TMOUT (-50) /*!< polling failure or timeout */ +#define E_DLT (-51) /*!< waiting object deleted */ +#define E_CLS (-52) /*!< waiting object state changed */ +#define E_WBLK (-57) /*!< non-blocking accepted */ +#define E_BOVR (-58) /*!< buffer overflow */ +#define E_OPNED (-6) /*!< device is opened */ +#define E_CLSED (-7) /*!< device is closed */ +/** @} end of name */ + +/** + * \name Generate And Decompose Error Code + * @{ + */ +#ifndef ERCD +/** generate error code using main error code and sub error code */ +#define ERCD(mercd, sercd) \ + ((uint32_t)((((uint32_t) sercd) << 8) | (((uint32_t) mercd) & 0xffU))) +#endif /* ERCD */ + +#ifndef MERCD +#ifdef INT8_MAX +/** get main error code from error code */ +#define MERCD(ercd) ((uint32_t)((int8_t)(ercd))) +#else /* INT8_MAX */ +/** get main error code from error code */ +#define MERCD(ercd) ((uint32_t)(((uint32_t) ercd) | ~0xffU)) +#endif /* INT8_MAX */ +#endif /* MERCD */ + +#ifndef SERCD +/** get sub error code from error code */ +#define SERCD(ercd) ((uint32_t)((ercd) >> 8)) +#endif /* SERCD */ +/** @} end of name */ + +/** + * \name Check Error + * @{ + */ +/** + * \brief check an expression to see if it is right, and when error + * set the ercd, and goto exit_label + * \param EXPR the expression that need to be checked (==0 failed) + * \param ERCD MUST pass a variable to here to get the error code + * \param ERROR_CODE error code that pass to ERCD + * \param EXIT_LABEL a label to go when error happens + */ +#define CHECK_EXP(EXPR, ERCD, ERROR_CODE, EXIT_LABEL) { \ + if (_arc_rarely(!(EXPR))) { \ + ERCD = (ERROR_CODE); \ + goto EXIT_LABEL; \ + } \ + } +/** + * \brief check an expression to see if it is right, and when error + * directly goto exit_label + * \param EXPR the expression that need to be checked (==0 failed) + * \param EXIT_LABEL a label to go when error happens + * \retval + */ +#define CHECK_EXP_NOERCD(EXPR, EXIT_LABEL) { \ + if (_arc_rarely(!(EXPR))) { \ + goto EXIT_LABEL; \ + } \ + } +/** check cnt bytes align, 1 for aligned, 0 for not-aligned */ +#define CHECK_ALIGN_BYTES(pointer, cnt) ((((uint32_t)(pointer)) & (cnt-1)) == 0) +/** check 2 bytes align, 1 for aligned, 0 for not-aligned */ +#define CHECK_ALIGN_2BYTES(pointer) ((((uint32_t)(pointer)) & 0x1) == 0) +/** check 4 bytes align, 1 for aligned, 0 for not-aligned */ +#define CHECK_ALIGN_4BYTES(pointer) ((((uint32_t)(pointer)) & 0x3) == 0) +/** check 8 bytes align, 1 for aligned, 0 for not-aligned */ +#define CHECK_ALIGN_8BYTES(pointer) ((((uint32_t)(pointer)) & 0x7) == 0) +/** @} end of name */ + +#ifdef __cplusplus +} +#endif + +#endif /* _EMBARC_ERROR_H_ */ +/** @} end of group EMBARC_ERROR */ diff --git a/hw/mcu/arc/src/ext/sdk/inc/embARC_toolchain.h b/hw/mcu/arc/src/ext/sdk/inc/embARC_toolchain.h new file mode 100644 index 000000000..37aef6606 --- /dev/null +++ b/hw/mcu/arc/src/ext/sdk/inc/embARC_toolchain.h @@ -0,0 +1,121 @@ +/* ------------------------------------------ + * Copyright (c) 2016, Synopsys, Inc. All rights reserved. + + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + + * 1) Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + + * 2) 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. + + * 3) Neither the name of the Synopsys, Inc., nor the names of its contributors may + * be used to endorse or promote products derived from this software without + * specific prior written permission. + + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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. + * + * \version 2016.05 + * \date 2014-12-25 + * \author Wayne Ren(Wei.Ren@synopsys.com) +--------------------------------------------- */ + +/** + * \file + * \ingroup TOOLCHAIN + * \brief toolchain dependent definitions + */ + +#include /* C99 standard lib */ +#include /* C99 standard lib */ +#include /* C99 standard lib */ +#include /* C99 standard lib */ + +#include "embARC_BSP_config.h" + +/** + * \addtogroup TOOLCHAIN + * @{ + */ + +#ifndef _EMBARC_TOOLCHAIN_H_ +#define _EMBARC_TOOLCHAIN_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * macro definitions of compiler extend function + */ +#ifndef __cplusplus /* C++ supports inline */ +#if __STDC_VERSION__ < 199901L /* C99 supports inline */ +#ifndef inline +#define inline __inline__ /* inline function */ +#endif +#endif /* __STDC_VERSION__ < 199901L */ +#endif /* __cplusplus */ + +#ifndef Inline +#define Inline static __inline__ /* inline function */ +#endif + +#ifndef __cplusplus /* C++ supports asm */ +#ifndef asm +#define asm __asm__ /* inline asm */ +#endif +#endif /* __cplusplus */ + +#ifndef Asm +#define Asm __asm__ volatile /* inline asm (no optimization) */ +#endif + +/* compiler attributes */ +#define EMBARC_FORCEINLINE __attribute__((always_inline)) +#define EMBARC_NOINLINE __attribute__((noinline)) +#define EMBARC_PACKED __attribute__((packed)) +#define EMBARC_WEAK __attribute__((weak)) +#define EMBARC_ALIAS(f) __attribute__((weak, alias (#f))) +#define EMBARC_LINKTO(f) __attribute__((alias (#f))) +#define EMBARC_NORETURN __attribute__((noreturn)) +#define EMBARC_NAKED __attribute__((naked)) /* function without return */ +#define EMBARC_ALIGNED(x) __attribute__((aligned(x))) + + +/* array count macro */ +#define EMBARC_ARRAY_COUNT(x) (sizeof(x)/sizeof(x[0])) + +/* convert macro argument to string */ +/* note: this needs one level of indirection, accomplished with the helper macro + * __EMBARC_TO_STRING */ +#define __EMBARC_TO_STRING(x) #x +#define EMBARC_TO_STRING(x) __EMBARC_TO_STRING(x) + +#if defined(__GNU__) +/* GNU tool specific definitions */ + +#elif defined(__MW__) +/* Metaware tool specific definitions */ +/* Metaware toolchain related definitions */ + +#else +#error "unsupported toolchain" +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* _EMBARC_TOOLCHAIN_H_ */ +/** }@ */ diff --git a/kernel/os/include/os/arch/arc/os/os_arch.h b/kernel/os/include/os/arch/arc/os/os_arch.h new file mode 100755 index 000000000..5092e544d --- /dev/null +++ b/kernel/os/include/os/arch/arc/os/os_arch.h @@ -0,0 +1,80 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. + */ + +#ifndef _OS_ARCH_ARC_H +#define _OS_ARCH_ARC_H + +#include +#include "mcu/mcu_arc.h" +#include "os/os_time.h" +#include "os/os_error.h" + +#ifdef __cplusplus +extern "C" { +#endif + +struct os_task; + +/* Run in user or kernel mode */ +#define OS_RUN_USER (0) +#define OS_RUN_KERNEL (1) + +/* Stores interrupt enable/disable state. */ +typedef uint32_t os_sr_t; + +/* Stack type, aligned to a 32-bit word. */ +#define OS_STACK_PATTERN (0xdeadbeef) + +typedef uint32_t os_stack_t; +#define OS_ALIGNMENT (4) +#define OS_STACK_ALIGNMENT (8) + +/* + * Stack sizes for common OS tasks + */ +#define OS_SANITY_STACK_SIZE (64) +#define OS_IDLE_STACK_SIZE (64) + +#define OS_STACK_ALIGN(__nmemb) \ + (OS_ALIGN((__nmemb), OS_STACK_ALIGNMENT)) + +/* Enter a critical section, save processor state, and block interrupts */ +#define OS_ENTER_CRITICAL(__os_sr) (__os_sr = os_arch_save_sr()) +/* Exit a critical section, restore processor state and unblock interrupts */ +#define OS_EXIT_CRITICAL(__os_sr) (os_arch_restore_sr(__os_sr)) +#define OS_ASSERT_CRITICAL() (assert(os_arch_in_critical())) + +os_stack_t *os_arch_task_stack_init(struct os_task *, os_stack_t *, int); +void timer_handler(void); +void os_arch_ctx_sw(struct os_task *); +os_sr_t os_arch_save_sr(void); +void os_arch_restore_sr(os_sr_t); +int os_arch_in_critical(void); +void os_arch_init(void); +os_error_t os_arch_os_init(void); +os_error_t os_arch_os_start(void); +void os_set_env(os_stack_t *); +void os_arch_init_task_stack(os_stack_t *sf); +void os_default_irq_asm(void); + +#ifdef __cplusplus +} +#endif + +#endif /* _OS_ARCH_ARM_H */ diff --git a/kernel/os/src/arch/arc/os_arc.s b/kernel/os/src/arch/arc/os_arc.s new file mode 100755 index 000000000..69c14f162 --- /dev/null +++ b/kernel/os/src/arch/arc/os_arc.s @@ -0,0 +1,253 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 "inc/arc/arc.h" +#include "inc/arc/arc_asm_common.h" + + .file "os_arc.s" + +/*--------------------------------------------------------------- + * Normal interrupt entry code. + *-------------------------------------------------------------*/ + .global exc_entry_int + .align 4 +exc_entry_int: + /* disable interrupts */ + clri + +#if ARC_FEATURE_FIRQ == 1 +#if ARC_FEATURE_RGF_NUM_BANKS > 1 + /* check whether it is P0 interrupt */ + lr r0, [AUX_IRQ_ACT] + btst r0, 0 + bnz exc_entry_firq +#else + PUSH r10 + lr r10, [AUX_IRQ_ACT] + btst r10, 0 + POP r10 + bnz exc_entry_firq +#endif +#endif + /* Pushes r12, gp, fp, ilink, r30 and reserves one location */ + INTERRUPT_PROLOGUE + + /* Temporarily save current stack pointer */ + mov blink, sp + + /* + * Increment nested exception count. If within a nested exception the + * stack pointer is already set. If first exception, we use the exception + * stack going forward. The exception stack is a firmware created + * construct. + */ + ld r3, [exc_nest_count] + add r2, r3, 1 + st r2, [exc_nest_count] + cmp r3, 0 + bne irq_handler_1 + mov sp, _e_stack + +irq_handler_1: + /* Save old stack pointer */ + PUSH blink + + /* Get address of interrupt in r2 */ + lr r0, [AUX_IRQ_CAUSE] + sr r0, [AUX_IRQ_SELECT] + mov r1, exc_int_handler_table + ld.as r2, [r1, r0] + + /* handle software triggered interrupt */ + lr r3, [AUX_IRQ_HINT] + cmp r3, r0 + bne.d irq_hint_handled + xor r3, r3, r3 + sr r3, [AUX_IRQ_HINT] +irq_hint_handled: + /* + * Enable interrupts to allow higher priority interrupts to preempt. + * Handle current interrupt + */ + seti + jl [r2] + + /* Disable interrupts */ + clri + + /* Restore saved stack pointer */ + POP blink + mov sp, blink + + /* + * Decrement nested exception count. If nested, simply return. + * If not, check for context switch + */ + mov r1, exc_nest_count + ld r0, [r1] + sub r0, r0, 1 + cmp r0, 0 + bne.d ret_int + st r0, [r1] + + /* Check if we should be running a different task */ + mov r3, g_os_run_list + ld r2, [r3] + mov r3, g_current_task + ld r1, [r3] + cmp r1, r2 + beq ret_int + + /* Save remaining registers on current task stack */ + SAVE_CALLEE_REGS + + /* + * Current task is in r1 and task to run in r2. We need to: + * -> Save current stack pointer in cureren task. + * -> Set current task to new task to be run. + * -> Get stack pointer of new task. + */ + st sp, [r1] + st r2, [r3] + ld sp, [r2] + + /* Restore registers of task that are not done by hw */ + RESTORE_CALLEE_REGS + + /* Return from the interrupt */ +ret_int: + INTERRUPT_EPILOGUE + rtie + + +/*--------------------------------------------------------------- + * Normal interrupt entry code. + *-------------------------------------------------------------*/ + .global exc_entry_firq + .align 4 +exc_entry_firq: + /* disable interrupt */ + clri + + SAVE_FIQ_EXC_REGS + + /* Increment nested exceptopn count */ + ld r0, [exc_nest_count] + add r0, r0, 1 + st r0, [exc_nest_count] + + /* r2 = _kernel_exc_tbl + irqno *4 */ + lr r0, [AUX_IRQ_CAUSE] + mov r1, exc_int_handler_table + ld.as r2, [r1, r0] + + /* for the case of software triggered interrupt */ + lr r3, [AUX_IRQ_HINT] + cmp r3, r0 + bne.d firq_hint_handled + xor r3, r3, r3 + sr r3, [AUX_IRQ_HINT] +firq_hint_handled: + /* jump to interrupt handler */ + jl [r2] + + /* no interrupts are allowed from here */ +firq_return: + + /* exc_nest_count -1 */ + ld r0, [exc_nest_count] + sub r0, r0, 1 + st r0, [exc_nest_count] + + RESTORE_FIQ_EXC_REGS + rtie + +/*--------------------------------------------------------------- + * Exception entry code. + *-------------------------------------------------------------*/ + .global exc_entry_cpu + .align 4 +exc_entry_cpu: + + EXCEPTION_PROLOGUE + + mov blink, sp + + /* + * Increment nested exception count. If within a nested exception the + * stack pointer is already set. If first exception, we use the exception + * stack going forward. The exception stack is a firmware created + * construct. + */ + ld r0, [exc_nest_count] + add r1, r0, 1 + st r1, [exc_nest_count] + cmp r0, 0 + bne exc_handler_1 + + mov sp, _e_stack +exc_handler_1: + /* Save old stack pointer */ + PUSH blink + + /* Call exception handler */ + lr r0, [AUX_ECR] + lsr r0, r0, 16 + mov r1, exc_int_handler_table + ld.as r2, [r1, r0] + jl [r2] + +ret_exc: + POP blink + mov sp, blink + mov r1, exc_nest_count + ld r0, [r1] + sub r0, r0, 1 + cmp r0, 0 + bne.d ret_exc_r_1 + st r0, [r1] + + /* Check if we should be running a different task */ + mov r3, g_os_run_list + ld r2, [r3] + mov r3, g_current_task + ld r1, [r3] + cmp r1, r2 + beq ret_exc_r_1 + + /* Save remaining registers on current task stack */ + SAVE_CALLEE_REGS + + /* + * Current task is in r1 and task to run in r2. We need to: + * -> Save current stack pointer in current task. + * -> Set current task to new task to be run. + * -> Get stack pointer of new task. + */ + st sp, [r1] + st r2, [r3] + ld sp, [r2] + + /* Restore registers of task that are not done by hw */ + RESTORE_CALLEE_REGS + +ret_exc_r_1: + EXCEPTION_EPILOGUE + rtie + diff --git a/kernel/os/src/arch/arc/os_arch_arc.c b/kernel/os/src/arch/arc/os_arch_arc.c new file mode 100755 index 000000000..3ccdd0800 --- /dev/null +++ b/kernel/os/src/arch/arc/os_arch_arc.c @@ -0,0 +1,340 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 +#include "os/os.h" +#include "inc/arc/arc_builtin.h" +#include "inc/arc/arc_exception.h" +#include "os/os_arch.h" +#include +#include +#include "os_priv.h" + +extern uint32_t _f_sdata; +extern uint32_t _e_stack; + +#define INITIAL_STATUS32 (0x80000000 | STATUS32_RESET_VALUE | \ + (((INT_PRI_MAX - INT_PRI_MIN) << 1) & 0x1e)) + +/* Stack frame structure */ +struct stack_frame { +#ifndef ARC_FEATURE_RF16 + uint32_t r25; + uint32_t r24; + uint32_t r23; + uint32_t r22; + uint32_t r21; + uint32_t r20; + uint32_t r19; + uint32_t r18; + uint32_t r17; + uint32_t r16; +#endif + uint32_t r15; + uint32_t r14; + uint32_t r13; + uint32_t bta; + uint32_t r30; + uint32_t ilink; + uint32_t fp; + uint32_t gp; + uint32_t r12; + + uint32_t r0; + uint32_t r1; + uint32_t r2; + uint32_t r3; +#ifndef ARC_FEATURE_RF16 + uint32_t r4; + uint32_t r5; + uint32_t r6; + uint32_t r7; + uint32_t r8; + uint32_t r9; +#endif + uint32_t r10; + uint32_t r11; + uint32_t blink; /* R31 */ + uint32_t lp_end; + uint32_t lp_start; + uint32_t lp_count; +#ifdef ARC_FEATURE_CODE_DENSITY + uint32_t ei_base; + uint32_t ldi_base; + uint32_t jli_base; +#endif + uint32_t pc; + uint32_t status32; +}; + +/* TODO: determine how we will deal with running un-privileged */ +//uint32_t os_flags = OS_RUN_KERNEL; + +void +timer_handler(void) +{ + os_time_advance(1); +} + +void +os_arch_ctx_sw(struct os_task *t) +{ + os_sched_ctx_sw_hook(t); + + if (!exc_sense()) { + asm("TRAP_S 1"); + } +} + +os_sr_t +os_arch_save_sr(void) +{ + os_sr_t sreg; + + sreg = cpu_lock_save(); + + return sreg; +} + +void +os_arch_restore_sr(os_sr_t isr_ctx) +{ + cpu_unlock_restore(isr_ctx); +} + +int +os_arch_in_critical(void) +{ + int status; + + status = (_arc_aux_read(AUX_STATUS32) & AUX_STATUS_MASK_IE) ? 0: 1; + return status; +} + +os_stack_t * +os_arch_task_stack_init(struct os_task *t, os_stack_t *stack_top, int size) +{ + os_stack_t *s; + uint32_t *tmp; + uint32_t init_val; + struct stack_frame *sf; + + /* Get stack frame pointer */ + s = (os_stack_t *) ((uint8_t *) stack_top - sizeof(*sf)); + sf = (struct stack_frame *) s; + + /* Initially set all values to 0 */ + memset(sf, 0, sizeof(struct stack_frame)); + +#ifndef ARC_FEATURE_RF16 + /* + * Init r25 - r16. We set each byte in the stack equal to its register + * number, in hex unless that register has a special purpose. For + * example, r25 = 0x25252525 and r3 = 0x03030303 + */ + init_val = 0x25252525; + tmp = s; + while (init_val >= 0x16161616) { + *tmp = init_val; + ++tmp; + if (init_val == 0x20202020) { + init_val = 0x19191919; + } else { + init_val -= 0x01010101; + } + } + + /* Init r4-r9 the same way */ + init_val = 0x04040404; + tmp = (uint32_t *)&sf->r4; + while (init_val <= 0x09090909) { + *tmp = init_val; + ++tmp; + init_val += 0x01010101; + } +#endif + + sf->r15 = 0x15151515; + sf->r14 = 0x14141414; + sf->r13 = 0x13131313; + sf->r11 = 0x12121212; + sf->r11 = 0x11111111; + sf->r10 = 0x10101010; + sf->r30 = 0x30303030; + sf->r3 = 0x03030303; + sf->r2 = 0x02020202; + sf->r1 = 0x01010101; + sf->r0 = (uint32_t)t->t_arg; + sf->pc = (uint32_t)t->t_func; + sf->status32 = INITIAL_STATUS32; /* this is the top of the stack */ + + /* We should never return! Hopefully this will generate an exception */ + sf->blink = 0xffffffff; + sf->gp = (uint32_t)&_f_sdata; + + + /* TODO: Do we need to do this? */ +#if 0 + /* Set registers R4 - R11 on stack. */ + os_arch_init_task_stack(s); +#endif + + return (s); +} + +/** + * os arch start + * + * Starts the OS. On ARC platforms this is called from the TRAP exception + * handler. + * + * @return uint32_t + */ +static void +os_arch_start(void) +{ + uint32_t *ptr32; + struct os_task *t; + + /* Get the highest priority ready to run to set the current task */ + t = os_sched_next_task(); + os_sched_set_current_task(t); + + /* TODO: hacked priority here to 0 */ + /* Intitialize and start system clock timer */ + os_tick_init(OS_TICKS_PER_SEC, 0); + + /* Mark the OS as started, right before we run our first task */ + g_os_started = 1; + + /* + * OK, here is what this code is doing. We took an exception (a TRAP) to + * get here. All tasks that have been created have their stack pointers + * (t->stackptr) set to where they would be if they were swapped out (in + * other words, not running). At the beginning of this function we set + * the current task to the head of the run list. This makes it look like + * the task at the head of the run list was the one we took the exception + * from. In other words, no task swap is needed. In the case the stack + * pointer in the task structure is off by the CALLEE registers as they + * would not have been pushed if the exception had actually taken place + * during the currently running task. The exception code pushes the + * current stack pointer to the top of the exception stack. This basically + * does this: *ptr = stack pointer where ptr = &_e_stack - 1 word. Thus, + * we need to overwrite the value at _e_stack - 4 with where the stack + * pointer in the task we want run would have been had an exception taken + * place when that task was running (add back the callee regs). + */ + ptr32 = &_e_stack; + --ptr32; + *ptr32 = (uint32_t)t->t_stackptr + offsetof(struct stack_frame, bta); +} + +/** + * os arch os start + * + * This gets called in _start prior to the os starting. For the ARC platform, + * we are currently not running in any task and the stack pointer being + * used is the exception stack pointer. + * + * @return os_error_t + */ +os_error_t +os_arch_os_start(void) +{ + /* Cause a trap with reason 0 (os start) */ + asm("TRAP_S 0"); + return 0; +} + +void +os_arch_trap_handler(void *exc_frame) +{ + uint32_t parameter; + + (void)exc_frame; + + /* + * Currently, only two traps should be generated: one to perform a context + * switch when a context switch was asked for at task (not interrupt) + * context. + */ + parameter = _arc_aux_read(AUX_ECR) & AUX_ECR_PARAM_MASK; + if (parameter == 0) { + os_arch_start(); + } +} + +os_error_t +os_arch_os_init(void) +{ + /* TODO: deal with this */ +#if 0 + os_error_t err; + int i; + + /* Cannot be called within an ISR */ + err = OS_ERR_IN_ISR; + if (__get_IPSR() == 0) { + err = OS_OK; + + /* Drop priority for all interrupts */ + for (i = 0; i < sizeof(NVIC->IP); i++) { + NVIC->IP[i] = -1; + } + + NVIC_SetVector(SVCall_IRQn, (uint32_t)SVC_Handler); + NVIC_SetVector(PendSV_IRQn, (uint32_t)PendSV_Handler); + NVIC_SetVector(SysTick_IRQn, (uint32_t)SysTick_Handler); + + /* + * Install default interrupt handler, which'll print out system + * state at the time of the interrupt, and few other regs which + * should help in trying to figure out what went wrong. + */ + NVIC_SetVector(NonMaskableInt_IRQn, (uint32_t)os_default_irq_asm); + NVIC_SetVector(-13, (uint32_t)os_default_irq_asm); + NVIC_SetVector(MemoryManagement_IRQn, (uint32_t)os_default_irq_asm); + NVIC_SetVector(BusFault_IRQn, (uint32_t)os_default_irq_asm); + NVIC_SetVector(UsageFault_IRQn, (uint32_t)os_default_irq_asm); + for (i = 0; i < NVIC_NUM_VECTORS - NVIC_USER_IRQ_OFFSET; i++) { + NVIC_SetVector(i, (uint32_t)os_default_irq_asm); + } + + /* Set the PendSV interrupt exception priority to the lowest priority */ + NVIC_SetPriority(PendSV_IRQn, PEND_SV_PRIO); + + /* Set the SVC interrupt to priority 0 (highest configurable) */ + NVIC_SetPriority(SVCall_IRQn, SVC_PRIO); + + /* Check if privileged or not */ + if ((__get_CONTROL() & 1) == 0) { + os_arch_init(); + } else { + svc_os_arch_init(); + } + } +#else + /* Set the trap handler exception */ + exc_handler_install(AUX_ECR_V_TRAP, os_arch_trap_handler); + + /* Init the idle task */ + os_init_idle_task(); +#endif + + return 0; +} diff --git a/kernel/os/src/arch/arc/os_fault.c b/kernel/os/src/arch/arc/os_fault.c new file mode 100644 index 000000000..b86a1b327 --- /dev/null +++ b/kernel/os/src/arch/arc/os_fault.c @@ -0,0 +1,175 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 "syscfg/syscfg.h" +#include "console/console.h" +#include "hal/hal_system.h" +#include "os/os.h" + +#if MYNEWT_VAL(OS_COREDUMP) +#include "coredump/coredump.h" +#endif + +#include +#include + +struct exception_frame { + uint32_t r0; + uint32_t r1; + uint32_t r2; + uint32_t r3; + uint32_t r12; + uint32_t lr; + uint32_t pc; + uint32_t psr; +}; + +struct trap_frame { + struct exception_frame *ef; + uint32_t r4; + uint32_t r5; + uint32_t r6; + uint32_t r7; + uint32_t r8; + uint32_t r9; + uint32_t r10; + uint32_t r11; + uint32_t lr; /* this LR holds EXC_RETURN */ +}; + +struct coredump_regs { + uint32_t r0; + uint32_t r1; + uint32_t r2; + uint32_t r3; + uint32_t r4; + uint32_t r5; + uint32_t r6; + uint32_t r7; + uint32_t r8; + uint32_t r9; + uint32_t r10; + uint32_t r11; + uint32_t r12; + uint32_t sp; + uint32_t lr; + uint32_t pc; + uint32_t psr; +}; + +#if MYNEWT_VAL(OS_COREDUMP) +static void +trap_to_coredump(struct trap_frame *tf, struct coredump_regs *regs) +{ +/* TODO: handle coredumps */ +#if 0 + regs->r0 = tf->ef->r0; + regs->r1 = tf->ef->r1; + regs->r2 = tf->ef->r2; + regs->r3 = tf->ef->r3; + regs->r4 = tf->r4; + regs->r5 = tf->r5; + regs->r6 = tf->r6; + regs->r7 = tf->r7; + regs->r8 = tf->r8; + regs->r9 = tf->r9; + regs->r10 = tf->r10; + regs->r11 = tf->r11; + regs->r12 = tf->ef->r12; + /* + * SP just before exception for the coredump. + * See ARMv7-M Architecture Ref Manual, sections B1.5.6 - B1.5.8 + * If floating point registers were pushed to stack, SP is adjusted + * by 0x68. + * Otherwise, SP is adjusted by 0x20. + * If SCB->CCR.STKALIGN is set, or fpu is active, SP is aligned to + * 8-byte boundary on exception entry. + * If this alignment adjustment happened, xPSR will have bit 9 set. + */ + if ((tf->lr & 0x10) == 0) { + /* + * Extended frame + */ + regs->sp = ((uint32_t)tf->ef) + 0x68; + if (tf->ef->psr & (1 << 9)) { + regs->sp += 4; + } + } else { + regs->sp = ((uint32_t)tf->ef) + 0x20; + if ((SCB->CCR & SCB_CCR_STKALIGN_Msk) & tf->ef->psr & (1 << 9)) { + regs->sp += 4; + } + } + regs->lr = tf->ef->lr; + regs->pc = tf->ef->pc; + regs->psr = tf->ef->psr; +#else +#endif +} +#endif + +void +__assert_func(const char *file, int line, const char *func, const char *e) +{ + int sr; + + OS_ENTER_CRITICAL(sr); + (void)sr; + console_blocking_mode(); + console_printf("Assert @ 0x%x\n", + (unsigned int)__builtin_return_address(0)); + if (hal_debugger_connected()) { + /* + * If debugger is attached, breakpoint before the trap. + */ + asm("BRK_S"); + } +/* TODO: Determine how this will be done */ +#if 0 + SCB->ICSR = SCB_ICSR_NMIPENDSET_Msk; + asm("isb"); +#endif + hal_system_reset(); +} + +void +os_default_irq(struct trap_frame *tf) +{ +#if MYNEWT_VAL(OS_COREDUMP) + struct coredump_regs regs; +#endif + + console_blocking_mode(); + console_printf("Unhandled interrupt , exception sp 0x%08lx\n", + (uint32_t)tf->ef); + console_printf(" r0:0x%08lx r1:0x%08lx r2:0x%08lx r3:0x%08lx\n", + tf->ef->r0, tf->ef->r1, tf->ef->r2, tf->ef->r3); + console_printf(" r4:0x%08lx r5:0x%08lx r6:0x%08lx r7:0x%08lx\n", + tf->r4, tf->r5, tf->r6, tf->r7); + console_printf(" r8:0x%08lx r9:0x%08lx r10:0x%08lx r11:0x%08lx\n", + tf->r8, tf->r9, tf->r10, tf->r11); + console_printf("r12:0x%08lx lr:0x%08lx pc:0x%08lx psr:0x%08lx\n", + tf->ef->r12, tf->ef->lr, tf->ef->pc, tf->ef->psr); + +#if MYNEWT_VAL(OS_COREDUMP) + trap_to_coredump(tf, ®s); + coredump_dump(®s, sizeof(regs)); +#endif + hal_system_reset(); +} ---------------------------------------------------------------- This is an automated message from the Apache Git Service. To respond to the message, please log on GitHub and use the URL above to go to the specific comment. For queries about this service, please contact Infrastructure at: users@infra.apache.org With regards, Apache Git Services