diff --git a/bsp/synopsys/embarc/SConscript b/bsp/synopsys/embarc/SConscript new file mode 100644 index 0000000000..9e086739af --- /dev/null +++ b/bsp/synopsys/embarc/SConscript @@ -0,0 +1,28 @@ +from building import * + +cwd = GetCurrentDir() + +embarc_arc_hal_SRCS = Split(""" +arc/arc_cache.c +arc/arc_exc_asm.S +arc/arc_exception.c +arc/arc_timer.c +arc/startup/arc_cxx_support.c +arc/startup/arc_startup.S +device/designware/uart/dw_uart.c +device/designware/gpio/dw_gpio.c +""") + + +ASFLAGS = ' -I' + cwd + +src = embarc_arc_hal_SRCS + +path = [cwd, + cwd + '/arc', + cwd + '/arc/startup' + ] + +group = DefineGroup('embarc', src, depend = [], CPPPATH = path, ASFLAGS = ASFLAGS) + +Return('group') diff --git a/bsp/synopsys/embarc/arc/arc_cache.c b/bsp/synopsys/embarc/arc/arc_cache.c new file mode 100644 index 0000000000..632a3e3291 --- /dev/null +++ b/bsp/synopsys/embarc/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/bsp/synopsys/embarc/arc/arc_exc_asm.S b/bsp/synopsys/embarc/arc/arc_exc_asm.S new file mode 100644 index 0000000000..7410db3154 --- /dev/null +++ b/bsp/synopsys/embarc/arc/arc_exc_asm.S @@ -0,0 +1,201 @@ +/* ------------------------------------------ + * 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 "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/bsp/synopsys/embarc/arc/arc_exception.c b/bsp/synopsys/embarc/arc/arc_exception.c new file mode 100644 index 0000000000..a256b0b394 --- /dev/null +++ b/bsp/synopsys/embarc/arc/arc_exception.c @@ -0,0 +1,501 @@ +/* ------------------------------------------ + * 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; + + Asm("kflag 1"); +} + + +/** + * \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); + Asm("kflag 1"); +} + +__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/bsp/synopsys/embarc/arc/arc_timer.c b/bsp/synopsys/embarc/arc/arc_timer.c new file mode 100644 index 0000000000..3d0c4b4f83 --- /dev/null +++ b/bsp/synopsys/embarc/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/bsp/synopsys/embarc/arc/startup/arc_cxx_support.c b/bsp/synopsys/embarc/arc/startup/arc_cxx_support.c new file mode 100644 index 0000000000..af842fddc6 --- /dev/null +++ b/bsp/synopsys/embarc/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/bsp/synopsys/embarc/arc/startup/arc_startup.S b/bsp/synopsys/embarc/arc/startup/arc_startup.S new file mode 100644 index 0000000000..26a6fdb519 --- /dev/null +++ b/bsp/synopsys/embarc/arc/startup/arc_startup.S @@ -0,0 +1,262 @@ +/* ------------------------------------------ + * 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 */ +/* early init of interrupt and exception */ + jl exc_int_init +/* 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/bsp/synopsys/embarc/device/designware/gpio/dw_gpio.c b/bsp/synopsys/embarc/device/designware/gpio/dw_gpio.c new file mode 100644 index 0000000000..ce79414fc6 --- /dev/null +++ b/bsp/synopsys/embarc/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/bsp/synopsys/embarc/device/designware/iic/dw_iic.h b/bsp/synopsys/embarc/device/designware/iic/dw_iic.h new file mode 100644 index 0000000000..55c551a67e --- /dev/null +++ b/bsp/synopsys/embarc/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/bsp/synopsys/embarc/device/designware/iic/dw_iic_hal.h b/bsp/synopsys/embarc/device/designware/iic/dw_iic_hal.h new file mode 100644 index 0000000000..f7ec0d27a2 --- /dev/null +++ b/bsp/synopsys/embarc/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/bsp/synopsys/embarc/device/designware/iic/dw_iic_hal_cfg.h b/bsp/synopsys/embarc/device/designware/iic/dw_iic_hal_cfg.h new file mode 100644 index 0000000000..1073162176 --- /dev/null +++ b/bsp/synopsys/embarc/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/bsp/synopsys/embarc/device/designware/spi/dw_spi.c b/bsp/synopsys/embarc/device/designware/spi/dw_spi.c new file mode 100644 index 0000000000..bea413b411 --- /dev/null +++ b/bsp/synopsys/embarc/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/bsp/synopsys/embarc/device/designware/spi/dw_spi.h b/bsp/synopsys/embarc/device/designware/spi/dw_spi.h new file mode 100644 index 0000000000..ef2faa90e6 --- /dev/null +++ b/bsp/synopsys/embarc/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/bsp/synopsys/embarc/device/designware/spi/dw_spi_hal.h b/bsp/synopsys/embarc/device/designware/spi/dw_spi_hal.h new file mode 100644 index 0000000000..b1a233c699 --- /dev/null +++ b/bsp/synopsys/embarc/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/bsp/synopsys/embarc/device/designware/spi/dw_spi_hal_cfg.h b/bsp/synopsys/embarc/device/designware/spi/dw_spi_hal_cfg.h new file mode 100644 index 0000000000..d6caf71466 --- /dev/null +++ b/bsp/synopsys/embarc/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/bsp/synopsys/embarc/device/designware/uart/dw_uart.c b/bsp/synopsys/embarc/device/designware/uart/dw_uart.c new file mode 100644 index 0000000000..999ee751e0 --- /dev/null +++ b/bsp/synopsys/embarc/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/bsp/synopsys/embarc/device/designware/uart/dw_uart.h b/bsp/synopsys/embarc/device/designware/uart/dw_uart.h new file mode 100644 index 0000000000..366c4fccc2 --- /dev/null +++ b/bsp/synopsys/embarc/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/bsp/synopsys/embarc/device/designware/uart/dw_uart_hal.h b/bsp/synopsys/embarc/device/designware/uart/dw_uart_hal.h new file mode 100644 index 0000000000..367894df99 --- /dev/null +++ b/bsp/synopsys/embarc/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/bsp/synopsys/embarc/device/device_hal/inc/dev_common.h b/bsp/synopsys/embarc/device/device_hal/inc/dev_common.h new file mode 100644 index 0000000000..623d54a611 --- /dev/null +++ b/bsp/synopsys/embarc/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/bsp/synopsys/embarc/device/device_hal/inc/dev_gpio.h b/bsp/synopsys/embarc/device/device_hal/inc/dev_gpio.h new file mode 100644 index 0000000000..290fd313a2 --- /dev/null +++ b/bsp/synopsys/embarc/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/bsp/synopsys/embarc/device/device_hal/inc/dev_iic.h b/bsp/synopsys/embarc/device/device_hal/inc/dev_iic.h new file mode 100644 index 0000000000..14106671ff --- /dev/null +++ b/bsp/synopsys/embarc/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/bsp/synopsys/embarc/device/device_hal/inc/dev_spi.h b/bsp/synopsys/embarc/device/device_hal/inc/dev_spi.h new file mode 100644 index 0000000000..4469654e54 --- /dev/null +++ b/bsp/synopsys/embarc/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/bsp/synopsys/embarc/device/device_hal/inc/dev_uart.h b/bsp/synopsys/embarc/device/device_hal/inc/dev_uart.h new file mode 100644 index 0000000000..c8e17d6421 --- /dev/null +++ b/bsp/synopsys/embarc/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/bsp/synopsys/embarc/inc/arc/arc.h b/bsp/synopsys/embarc/inc/arc/arc.h new file mode 100644 index 0000000000..91c0a3850e --- /dev/null +++ b/bsp/synopsys/embarc/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/bsp/synopsys/embarc/inc/arc/arc_builtin.h b/bsp/synopsys/embarc/inc/arc/arc_builtin.h new file mode 100644 index 0000000000..d9b76124ff --- /dev/null +++ b/bsp/synopsys/embarc/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/bsp/synopsys/embarc/inc/arc/arc_cache.h b/bsp/synopsys/embarc/inc/arc/arc_cache.h new file mode 100644 index 0000000000..dfbc7df9a5 --- /dev/null +++ b/bsp/synopsys/embarc/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/bsp/synopsys/embarc/inc/arc/arc_em.h b/bsp/synopsys/embarc/inc/arc/arc_em.h new file mode 100644 index 0000000000..cfb9636449 --- /dev/null +++ b/bsp/synopsys/embarc/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/bsp/synopsys/embarc/inc/arc/arc_exception.h b/bsp/synopsys/embarc/inc/arc/arc_exception.h new file mode 100644 index 0000000000..e485b159c3 --- /dev/null +++ b/bsp/synopsys/embarc/inc/arc/arc_exception.h @@ -0,0 +1,461 @@ +/* ------------------------------------------ + * 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 + +#endif /* _ARC_HAL_EXCEPTION_H_*/ diff --git a/bsp/synopsys/embarc/inc/arc/arc_feature_config.h b/bsp/synopsys/embarc/inc/arc/arc_feature_config.h new file mode 100644 index 0000000000..87b1913df5 --- /dev/null +++ b/bsp/synopsys/embarc/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/bsp/synopsys/embarc/inc/arc/arc_timer.h b/bsp/synopsys/embarc/inc/arc/arc_timer.h new file mode 100644 index 0000000000..b5237f31a9 --- /dev/null +++ b/bsp/synopsys/embarc/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/bsp/synopsys/embarc/inc/embARC_debug.h b/bsp/synopsys/embarc/inc/embARC_debug.h new file mode 100644 index 0000000000..092374622d --- /dev/null +++ b/bsp/synopsys/embarc/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/bsp/synopsys/embarc/inc/embARC_error.h b/bsp/synopsys/embarc/inc/embARC_error.h new file mode 100644 index 0000000000..9bd9c318aa --- /dev/null +++ b/bsp/synopsys/embarc/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/bsp/synopsys/embarc/inc/embARC_toolchain.h b/bsp/synopsys/embarc/inc/embARC_toolchain.h new file mode 100644 index 0000000000..37aef66064 --- /dev/null +++ b/bsp/synopsys/embarc/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/bsp/synopsys/emsk_em9d/.config b/bsp/synopsys/emsk_em9d/.config new file mode 100644 index 0000000000..55759f136a --- /dev/null +++ b/bsp/synopsys/emsk_em9d/.config @@ -0,0 +1,402 @@ +# +# Automatically generated file; DO NOT EDIT. +# RT-Thread Configuration +# + +# +# RT-Thread Kernel +# +CONFIG_RT_NAME_MAX=8 +# CONFIG_RT_USING_SMP is not set +CONFIG_RT_ALIGN_SIZE=4 +# CONFIG_RT_THREAD_PRIORITY_8 is not set +CONFIG_RT_THREAD_PRIORITY_32=y +# CONFIG_RT_THREAD_PRIORITY_256 is not set +CONFIG_RT_THREAD_PRIORITY_MAX=32 +CONFIG_RT_TICK_PER_SECOND=100 +CONFIG_RT_USING_OVERFLOW_CHECK=y +CONFIG_RT_USING_HOOK=y +CONFIG_RT_USING_IDLE_HOOK=y +CONFIG_RT_IDEL_HOOK_LIST_SIZE=4 +CONFIG_IDLE_THREAD_STACK_SIZE=256 +# CONFIG_RT_USING_TIMER_SOFT is not set +CONFIG_RT_DEBUG=y +# CONFIG_RT_DEBUG_INIT_CONFIG is not set +# CONFIG_RT_DEBUG_THREAD_CONFIG is not set +# CONFIG_RT_DEBUG_SCHEDULER_CONFIG is not set +# CONFIG_RT_DEBUG_IPC_CONFIG is not set +# CONFIG_RT_DEBUG_TIMER_CONFIG is not set +# CONFIG_RT_DEBUG_IRQ_CONFIG is not set +# CONFIG_RT_DEBUG_MEM_CONFIG is not set +# CONFIG_RT_DEBUG_SLAB_CONFIG is not set +# CONFIG_RT_DEBUG_MEMHEAP_CONFIG is not set +# CONFIG_RT_DEBUG_MODULE_CONFIG is not set + +# +# Inter-Thread communication +# +CONFIG_RT_USING_SEMAPHORE=y +CONFIG_RT_USING_MUTEX=y +CONFIG_RT_USING_EVENT=y +CONFIG_RT_USING_MAILBOX=y +CONFIG_RT_USING_MESSAGEQUEUE=y +# CONFIG_RT_USING_SIGNALS is not set + +# +# Memory Management +# +CONFIG_RT_USING_MEMPOOL=y +# CONFIG_RT_USING_MEMHEAP is not set +# CONFIG_RT_USING_NOHEAP is not set +CONFIG_RT_USING_SMALL_MEM=y +# CONFIG_RT_USING_SLAB is not set +# CONFIG_RT_USING_MEMTRACE is not set +CONFIG_RT_USING_HEAP=y + +# +# Kernel Device Object +# +CONFIG_RT_USING_DEVICE=y +# CONFIG_RT_USING_DEVICE_OPS is not set +# CONFIG_RT_USING_INTERRUPT_INFO is not set +CONFIG_RT_USING_CONSOLE=y +CONFIG_RT_CONSOLEBUF_SIZE=128 +CONFIG_RT_CONSOLE_DEVICE_NAME="uart1" +CONFIG_RT_VER_NUM=0x40000 +# CONFIG_ARCH_CPU_STACK_GROWS_UPWARD is not set + +# +# RT-Thread Components +# +CONFIG_RT_USING_COMPONENTS_INIT=y +# CONFIG_RT_USING_USER_MAIN is not set + +# +# C++ features +# +# CONFIG_RT_USING_CPLUSPLUS is not set + +# +# Command shell +# +CONFIG_RT_USING_FINSH=y +CONFIG_FINSH_THREAD_NAME="tshell" +CONFIG_FINSH_USING_HISTORY=y +CONFIG_FINSH_HISTORY_LINES=5 +CONFIG_FINSH_USING_SYMTAB=y +CONFIG_FINSH_USING_DESCRIPTION=y +# CONFIG_FINSH_ECHO_DISABLE_DEFAULT is not set +CONFIG_FINSH_THREAD_PRIORITY=20 +CONFIG_FINSH_THREAD_STACK_SIZE=4096 +CONFIG_FINSH_CMD_SIZE=80 +# CONFIG_FINSH_USING_AUTH is not set +CONFIG_FINSH_USING_MSH=y +CONFIG_FINSH_USING_MSH_DEFAULT=y +# CONFIG_FINSH_USING_MSH_ONLY is not set +CONFIG_FINSH_ARG_MAX=10 + +# +# Device virtual file system +# +CONFIG_RT_USING_DFS=y +CONFIG_DFS_USING_WORKDIR=y +CONFIG_DFS_FILESYSTEMS_MAX=2 +CONFIG_DFS_FILESYSTEM_TYPES_MAX=2 +CONFIG_DFS_FD_MAX=16 +# CONFIG_RT_USING_DFS_MNTTABLE is not set +# CONFIG_RT_USING_DFS_ELMFAT is not set +CONFIG_RT_USING_DFS_DEVFS=y +# CONFIG_RT_USING_DFS_ROMFS is not set +# CONFIG_RT_USING_DFS_RAMFS is not set +# CONFIG_RT_USING_DFS_UFFS is not set +# CONFIG_RT_USING_DFS_JFFS2 is not set +# CONFIG_RT_USING_DFS_NFS is not set + +# +# Device Drivers +# +CONFIG_RT_USING_DEVICE_IPC=y +CONFIG_RT_PIPE_BUFSZ=512 +CONFIG_RT_USING_SERIAL=y +CONFIG_RT_SERIAL_USING_DMA=y +# CONFIG_RT_USING_CAN is not set +# CONFIG_RT_USING_HWTIMER is not set +# CONFIG_RT_USING_CPUTIME is not set +# CONFIG_RT_USING_I2C is not set +CONFIG_RT_USING_PIN=y +# CONFIG_RT_USING_ADC is not set +# CONFIG_RT_USING_PWM is not set +# CONFIG_RT_USING_MTD_NOR is not set +# CONFIG_RT_USING_MTD_NAND is not set +# CONFIG_RT_USING_MTD is not set +# CONFIG_RT_USING_PM is not set +# CONFIG_RT_USING_RTC is not set +# CONFIG_RT_USING_SDIO is not set +# CONFIG_RT_USING_SPI is not set +# CONFIG_RT_USING_WDT is not set +# CONFIG_RT_USING_AUDIO is not set + +# +# Using WiFi +# +# CONFIG_RT_USING_WIFI is not set + +# +# Using USB +# +# CONFIG_RT_USING_USB_HOST is not set +# CONFIG_RT_USING_USB_DEVICE is not set + +# +# POSIX layer and C standard library +# +CONFIG_RT_USING_LIBC=y +# CONFIG_RT_USING_PTHREADS is not set +# CONFIG_RT_USING_POSIX is not set +# CONFIG_RT_USING_MODULE is not set + +# +# Network +# + +# +# Socket abstraction layer +# +CONFIG_RT_USING_SAL=y + +# +# protocol stack implement +# +CONFIG_SAL_USING_LWIP=y +CONFIG_SAL_USING_AT=y +# CONFIG_SAL_USING_POSIX is not set +CONFIG_SAL_SOCKETS_NUM=16 +CONFIG_SAL_PROTO_FAMILIES_NUM=4 + +# +# light weight TCP/IP stack +# +CONFIG_RT_USING_LWIP=y +# CONFIG_RT_USING_LWIP141 is not set +CONFIG_RT_USING_LWIP202=y +# CONFIG_RT_USING_LWIP210 is not set +# CONFIG_RT_USING_LWIP_IPV6 is not set +CONFIG_RT_LWIP_IGMP=y +CONFIG_RT_LWIP_ICMP=y +# CONFIG_RT_LWIP_SNMP is not set +CONFIG_RT_LWIP_DNS=y +CONFIG_RT_LWIP_DHCP=y +CONFIG_IP_SOF_BROADCAST=1 +CONFIG_IP_SOF_BROADCAST_RECV=1 + +# +# Static IPv4 Address +# +CONFIG_RT_LWIP_IPADDR="192.168.1.30" +CONFIG_RT_LWIP_GWADDR="192.168.1.1" +CONFIG_RT_LWIP_MSKADDR="255.255.255.0" +CONFIG_RT_LWIP_UDP=y +CONFIG_RT_LWIP_TCP=y +# CONFIG_RT_LWIP_RAW is not set +# CONFIG_RT_LWIP_PPP is not set +CONFIG_RT_MEMP_NUM_NETCONN=8 +CONFIG_RT_LWIP_PBUF_NUM=16 +CONFIG_RT_LWIP_RAW_PCB_NUM=4 +CONFIG_RT_LWIP_UDP_PCB_NUM=4 +CONFIG_RT_LWIP_TCP_PCB_NUM=4 +CONFIG_RT_LWIP_TCP_SEG_NUM=40 +CONFIG_RT_LWIP_TCP_SND_BUF=8196 +CONFIG_RT_LWIP_TCP_WND=8196 +CONFIG_RT_LWIP_TCPTHREAD_PRIORITY=10 +CONFIG_RT_LWIP_TCPTHREAD_MBOX_SIZE=8 +CONFIG_RT_LWIP_TCPTHREAD_STACKSIZE=1024 +# CONFIG_LWIP_NO_RX_THREAD is not set +# CONFIG_LWIP_NO_TX_THREAD is not set +CONFIG_RT_LWIP_ETHTHREAD_PRIORITY=12 +CONFIG_RT_LWIP_ETHTHREAD_STACKSIZE=1024 +CONFIG_RT_LWIP_ETHTHREAD_MBOX_SIZE=8 +# CONFIG_RT_LWIP_REASSEMBLY_FRAG is not set +CONFIG_LWIP_NETIF_STATUS_CALLBACK=1 +CONFIG_SO_REUSE=1 +CONFIG_LWIP_SO_RCVTIMEO=1 +CONFIG_LWIP_SO_SNDTIMEO=1 +CONFIG_LWIP_SO_RCVBUF=1 +# CONFIG_RT_LWIP_NETIF_LOOPBACK is not set +CONFIG_LWIP_NETIF_LOOPBACK=0 +# CONFIG_RT_LWIP_STATS is not set +# CONFIG_RT_LWIP_DEBUG is not set + +# +# Modbus master and slave stack +# +# CONFIG_RT_USING_MODBUS is not set + +# +# AT commands +# +CONFIG_RT_USING_AT=y +# CONFIG_AT_DEBUG is not set +# CONFIG_AT_USING_SERVER is not set +CONFIG_AT_USING_CLIENT=y +CONFIG_AT_CLIENT_NUM_MAX=1 +CONFIG_AT_USING_SOCKET=y +CONFIG_AT_USING_CLI=y +# CONFIG_AT_PRINT_RAW_CMD is not set +CONFIG_AT_SW_VERSION_NUM=0x10200 +# CONFIG_LWIP_USING_DHCPD is not set + +# +# VBUS(Virtual Software BUS) +# +# CONFIG_RT_USING_VBUS is not set + +# +# Utilities +# +# CONFIG_RT_USING_LOGTRACE is not set +# CONFIG_RT_USING_RYM is not set +# CONFIG_RT_USING_ULOG is not set +# CONFIG_RT_USING_UTEST is not set + +# +# RT-Thread online packages +# + +# +# IoT - internet of things +# +# CONFIG_PKG_USING_PAHOMQTT is not set +# CONFIG_PKG_USING_WEBCLIENT is not set +# CONFIG_PKG_USING_MONGOOSE is not set +# CONFIG_PKG_USING_WEBTERMINAL is not set +# CONFIG_PKG_USING_CJSON is not set +# CONFIG_PKG_USING_JSMN is not set +# CONFIG_PKG_USING_LJSON is not set +# CONFIG_PKG_USING_EZXML is not set +# CONFIG_PKG_USING_NANOPB is not set + +# +# Wi-Fi +# + +# +# Marvell WiFi +# +# CONFIG_PKG_USING_WLANMARVELL is not set + +# +# Wiced WiFi +# +# CONFIG_PKG_USING_WLAN_WICED is not set +# CONFIG_PKG_USING_COAP is not set +# CONFIG_PKG_USING_NOPOLL is not set +# CONFIG_PKG_USING_NETUTILS is not set +CONFIG_PKG_USING_AT_DEVICE=y +CONFIG_PKG_AT_DEVICE_PATH="/packages/iot/at_device" +CONFIG_PKG_AT_INIT_BY_THREAD=y +# CONFIG_AT_DEVICE_M26 is not set +# CONFIG_AT_DEVICE_EC20 is not set +CONFIG_AT_DEVICE_ESP8266=y +# CONFIG_AT_DEVICE_NOT_SELECTED is not set +CONFIG_AT_DEVICE_SOCKETS_NUM=5 +CONFIG_AT_DEVICE_NAME="uart0" +CONFIG_AT_DEVICE_RECV_BUFF_LEN=512 +CONFIG_AT_DEVICE_WIFI_SSID="embarc" +CONFIG_AT_DEVICE_WIFI_PASSWORD="qazwsxedc" +CONFIG_PKG_USING_AT_DEVICE_LATEST_VERSION=y +# CONFIG_PKG_USING_AT_DEVICE_V100 is not set +# CONFIG_PKG_USING_AT_DEVICE_V110 is not set +CONFIG_PKG_AT_DEVICE_VER="latest" + +# +# IoT Cloud +# +# CONFIG_PKG_USING_ONENET is not set +# CONFIG_PKG_USING_GAGENT_CLOUD is not set +# CONFIG_PKG_USING_ALI_IOTKIT is not set +# CONFIG_PKG_USING_AZURE is not set + +# +# security packages +# +# CONFIG_PKG_USING_MBEDTLS is not set +# CONFIG_PKG_USING_libsodium is not set +# CONFIG_PKG_USING_TINYCRYPT is not set + +# +# language packages +# +# CONFIG_PKG_USING_LUA is not set +# CONFIG_PKG_USING_JERRYSCRIPT is not set +# CONFIG_PKG_USING_MICROPYTHON is not set + +# +# multimedia packages +# +# CONFIG_PKG_USING_OPENMV is not set +# CONFIG_PKG_USING_MUPDF is not set + +# +# tools packages +# +# CONFIG_PKG_USING_CMBACKTRACE is not set +# CONFIG_PKG_USING_EASYFLASH is not set +# CONFIG_PKG_USING_EASYLOGGER is not set +# CONFIG_PKG_USING_SYSTEMVIEW is not set + +# +# system packages +# +# CONFIG_PKG_USING_GUIENGINE is not set +# CONFIG_PKG_USING_CAIRO is not set +# CONFIG_PKG_USING_PIXMAN is not set +# CONFIG_PKG_USING_LWEXT4 is not set +# CONFIG_PKG_USING_PARTITION is not set +# CONFIG_PKG_USING_FAL is not set +# CONFIG_PKG_USING_SQLITE is not set +# CONFIG_PKG_USING_RTI is not set +# CONFIG_PKG_USING_LITTLEVGL2RTT is not set + +# +# peripheral libraries and drivers +# +# CONFIG_PKG_USING_STM32F4_HAL is not set +# CONFIG_PKG_USING_STM32F4_DRIVERS is not set +# CONFIG_PKG_USING_REALTEK_AMEBA is not set +# CONFIG_PKG_USING_SHT2X is not set +# CONFIG_PKG_USING_AHT10 is not set +# CONFIG_PKG_USING_AP3216C is not set +# CONFIG_PKG_USING_STM32_SDIO is not set + +# +# miscellaneous packages +# +# CONFIG_PKG_USING_LIBCSV is not set +# CONFIG_PKG_USING_OPTPARSE is not set +# CONFIG_PKG_USING_FASTLZ is not set +# CONFIG_PKG_USING_MINILZO is not set +# CONFIG_PKG_USING_QUICKLZ is not set +# CONFIG_PKG_USING_MULTIBUTTON is not set +# CONFIG_PKG_USING_CANFESTIVAL is not set +# CONFIG_PKG_USING_ZLIB is not set +# CONFIG_PKG_USING_DSTR is not set + +# +# sample package +# + +# +# samples: kernel and components samples +# +# CONFIG_PKG_USING_KERNEL_SAMPLES is not set +# CONFIG_PKG_USING_FILESYSTEM_SAMPLES is not set +# CONFIG_PKG_USING_NETWORK_SAMPLES is not set +# CONFIG_PKG_USING_PERIPHERAL_SAMPLES is not set + +# +# example package: hello +# +# CONFIG_PKG_USING_HELLO is not set +CONFIG_SOC_EMSK=y +CONFIG_EMSK_USING_UART0=y +CONFIG_EMSK_USING_UART1=y diff --git a/bsp/synopsys/emsk_em9d/Kconfig b/bsp/synopsys/emsk_em9d/Kconfig new file mode 100644 index 0000000000..1748a1e8ae --- /dev/null +++ b/bsp/synopsys/emsk_em9d/Kconfig @@ -0,0 +1,26 @@ +mainmenu "RT-Thread Configuration" + +config BSP_DIR + string + option env="BSP_ROOT" + default "." + +config RTT_DIR + string + option env="RTT_ROOT" + default "../.." + +config PKGS_DIR + string + option env="PKGS_ROOT" + default "packages" + +source "$RTT_DIR/Kconfig" +source "$PKGS_DIR/Kconfig" + +config SOC_EMSK + bool + select ARCH_ARC_EM + default y + +source "$BSP_DIR/drivers/Kconfig" diff --git a/bsp/synopsys/emsk_em9d/SConscript b/bsp/synopsys/emsk_em9d/SConscript new file mode 100644 index 0000000000..86b6c891cd --- /dev/null +++ b/bsp/synopsys/emsk_em9d/SConscript @@ -0,0 +1,18 @@ +# for module compiling +import os +Import('RTT_ROOT') + +cwd = str(Dir('#')) +objs = [] +list = os.listdir(cwd) + +ASFLAGS = ' -I' + cwd + +objs = objs + SConscript(os.path.join(cwd, '../embarc/SConscript')) + +for d in list: + path = os.path.join(cwd, d) + if os.path.isfile(os.path.join(path, 'SConscript')): + objs = objs + SConscript(os.path.join(d, 'SConscript')) + +Return('objs') diff --git a/bsp/synopsys/emsk_em9d/SConstruct b/bsp/synopsys/emsk_em9d/SConstruct new file mode 100644 index 0000000000..a93d89ee74 --- /dev/null +++ b/bsp/synopsys/emsk_em9d/SConstruct @@ -0,0 +1,52 @@ +import os +import sys +import rtconfig + +if os.getenv('RTT_ROOT'): + RTT_ROOT = os.getenv('RTT_ROOT') +else: + RTT_ROOT = os.path.normpath(os.getcwd() + '/../../..') + +sys.path = sys.path + [os.path.join(RTT_ROOT, 'tools')] + +try: + from building import * +except: + print('Cannot found RT-Thread root directory, please check RTT_ROOT') + print(RTT_ROOT) + exit(-1) + +TARGET = 'rtthread_snps_emsk_em9d.' + rtconfig.TARGET_EXT + +# use scons --gdb to debug emsk +AddOption('--gdb', + dest = 'gdb', + action = 'store_true', + default = False, + help = 'use gdb to debug the elf') + +if GetOption('gdb'): + if os.path.isfile(rtconfig.TARGET): + os.system(rtconfig.DBG + rtconfig.DBG_HW_FLAGS + rtconfig.TARGET) + else: + print rtconfig.TARGET + 'not exist, please build first!!' + exit(0) + +env = Environment(tools = ['mingw'], + AS = rtconfig.AS, ASFLAGS = rtconfig.AFLAGS, + CC = rtconfig.CC, CCFLAGS = rtconfig.CFLAGS, + AR = rtconfig.AR, ARFLAGS = '-rc', + LINK = rtconfig.LINK, LINKFLAGS = rtconfig.LFLAGS) +env.PrependENVPath('PATH', rtconfig.EXEC_PATH) + +Export('RTT_ROOT') +Export('rtconfig') + +# prepare building environment +objs = PrepareBuilding(env, RTT_ROOT) + +# if the linker script changed, relink the target +Depends(TARGET, rtconfig.LINK_SCRIPT) + +# make a building +DoBuilding(TARGET, objs) diff --git a/bsp/synopsys/emsk_em9d/applications/SConscript b/bsp/synopsys/emsk_em9d/applications/SConscript new file mode 100644 index 0000000000..01eb940dfb --- /dev/null +++ b/bsp/synopsys/emsk_em9d/applications/SConscript @@ -0,0 +1,11 @@ +Import('RTT_ROOT') +Import('rtconfig') +from building import * + +cwd = os.path.join(str(Dir('#')), 'applications') +src = Glob('*.c') +CPPPATH = [cwd, str(Dir('#'))] + +group = DefineGroup('Applications', src, depend = [''], CPPPATH = CPPPATH) + +Return('group') diff --git a/bsp/synopsys/emsk_em9d/applications/application.c b/bsp/synopsys/emsk_em9d/applications/application.c new file mode 100644 index 0000000000..3e12c0ba76 --- /dev/null +++ b/bsp/synopsys/emsk_em9d/applications/application.c @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2018, Synopsys, Inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +/* thread phase init */ +static void rt_init_thread_entry(void *parameter) +{ + /* do component initialization */ + rt_components_init(); + + /* add your initialization here */ +} + +int rt_application_init() +{ + rt_thread_t tid; + + tid = rt_thread_create("init", rt_init_thread_entry, RT_NULL, 2048, + RT_THREAD_PRIORITY_MAX/3, 20); + if (tid != RT_NULL) + rt_thread_startup(tid); + + return 0; +} + diff --git a/bsp/synopsys/emsk_em9d/applications/startup.c b/bsp/synopsys/emsk_em9d/applications/startup.c new file mode 100644 index 0000000000..f561436272 --- /dev/null +++ b/bsp/synopsys/emsk_em9d/applications/startup.c @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2018, Synopsys, Inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include + +#include + +extern int rt_application_init(void); + +void rt_hw_interrupt_init(void) +{ + /* rt-thread specific interrupt and exception init */ +} + +/** + * This function will startup RT-Thread RTOS. + */ +void rtthread_startup(void) +{ + + /* initialize hardware interrupt */ + rt_hw_interrupt_init(); + + /* initialize board */ + rt_hw_board_init(); + + /* show RT-Thread version */ + rt_show_version(); + + /* initialize memory system */ +#ifdef RT_USING_HEAP + rt_system_heap_init(HEAP_BEGIN, HEAP_END); +#endif + + /* initialize scheduler system */ + rt_system_scheduler_init(); + + /* initialize system timer */ + rt_system_timer_init(); + + /* initialize soft timer thread */ + rt_system_timer_thread_init(); + + /* initialize application */ + rt_application_init(); + + /* initialize idle thread */ + rt_thread_idle_init(); + + /* start scheduler */ + rt_system_scheduler_start(); + + /* never reach here */ + return ; +} + +int board_main(void) +{ + /* disable interrupt first */ + rt_hw_interrupt_disable(); + + /* invoke rtthread_startup */ + rtthread_startup(); + + return 0; +} + diff --git a/bsp/synopsys/emsk_em9d/drivers/Kconfig b/bsp/synopsys/emsk_em9d/drivers/Kconfig new file mode 100644 index 0000000000..3cc4d3470d --- /dev/null +++ b/bsp/synopsys/emsk_em9d/drivers/Kconfig @@ -0,0 +1,10 @@ + +config EMSK_USING_UART0 + bool "Using UART0" + select RT_USING_SERIAL + default y + +config EMSK_USING_UART1 + bool "Using UART1" + select RT_USING_SERIAL + default y \ No newline at end of file diff --git a/bsp/synopsys/emsk_em9d/drivers/SConscript b/bsp/synopsys/emsk_em9d/drivers/SConscript new file mode 100644 index 0000000000..29272aa88e --- /dev/null +++ b/bsp/synopsys/emsk_em9d/drivers/SConscript @@ -0,0 +1,15 @@ +import copy +Import('RTT_ROOT') +Import('rtconfig') +from building import * + +cwd = GetCurrentDir() +src = Glob('*.c') + +ASFLAGS = ' -I' + cwd + +CPPPATH = [cwd] + +group = DefineGroup('Drivers', src, depend = [''], CPPPATH = CPPPATH, ASFLAGS = ASFLAGS) + +Return('group') diff --git a/bsp/synopsys/emsk_em9d/drivers/arc_core_config.h b/bsp/synopsys/emsk_em9d/drivers/arc_core_config.h new file mode 100644 index 0000000000..8340e94091 --- /dev/null +++ b/bsp/synopsys/emsk_em9d/drivers/arc_core_config.h @@ -0,0 +1,229 @@ +/* This file is automatically generated from tcf file. DO NOT EDIT */ +#ifndef __core_config_h + #define __core_config_h 1 + #define core_config_cir_identity 0x00000042 + #define core_config_cir_identity_chipid 0 + #define core_config_cir_identity_arcnum 0 + #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 0x0000c902 + #define core_config_bcr_rf_build_version 2 + #define core_config_bcr_rf_build_p 1 + #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 0x00010904 + #define core_config_bcr_dccm_build_cycles 0 + #define core_config_bcr_dccm_build_interleave 1 + #define core_config_bcr_dccm_build_size1 0 + #define core_config_bcr_dccm_build_size0 9 + #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_ap_build 0x00000405 + #define core_config_bcr_ap_build_version 5 + #define core_config_bcr_ap_build_type 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_xy_build 0x00001620 + #define core_config_bcr_xy_build_memsize 1 + #define core_config_bcr_xy_build_interleaved 1 + #define core_config_bcr_xy_build_config 2 + #define core_config_bcr_xy_build_version 32 + #define core_config_bcr_dsp_build 0x00003521 + #define core_config_bcr_dsp_build_wide 0 + #define core_config_bcr_dsp_build_itu_pa 1 + #define core_config_bcr_dsp_build_acc_shift 2 + #define core_config_bcr_dsp_build_comp 1 + #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_d 1 + #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_fpu_build 0x00000f02 + #define core_config_bcr_fpu_build_da 0 + #define core_config_bcr_fpu_build_dd 0 + #define core_config_bcr_fpu_build_dc 0 + #define core_config_bcr_fpu_build_df 0 + #define core_config_bcr_fpu_build_dp 0 + #define core_config_bcr_fpu_build_fd 0 + #define core_config_bcr_fpu_build_fm 0 + #define core_config_bcr_fpu_build_sd 1 + #define core_config_bcr_fpu_build_sc 1 + #define core_config_bcr_fpu_build_sf 1 + #define core_config_bcr_fpu_build_sp 1 + #define core_config_bcr_fpu_build_version 2 + #define core_config_bcr_bs_build 0x00000001 + #define core_config_bcr_bs_build_version 1 + #define core_config_bcr_agu_build 0x01988c01 + #define core_config_bcr_agu_build_accordian 1 + #define core_config_bcr_agu_build_wb_size 4 + #define core_config_bcr_agu_build_num_modifier 24 + #define core_config_bcr_agu_build_num_offset 8 + #define core_config_bcr_agu_build_num_addr 12 + #define core_config_bcr_agu_build_version 1 + #define core_config_bcr_dmac_build 0x000a0101 + #define core_config_bcr_dmac_build_int_cfg 1 + #define core_config_bcr_dmac_build_fifo 1 + #define core_config_bcr_dmac_build_chan_mem 0 + #define core_config_bcr_dmac_build_channels 1 + #define core_config_bcr_dmac_build_version 1 + #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 0x13101401 + #define core_config_bcr_irq_build_raz 0 + #define core_config_bcr_irq_build_f 1 + #define core_config_bcr_irq_build_p 3 + #define core_config_bcr_irq_build_exts 16 + #define core_config_bcr_irq_build_irqs 20 + #define core_config_bcr_irq_build_version 1 + #define core_config_bcr_pct_build 0x08080102 + #define core_config_bcr_pct_build_version 2 + #define core_config_bcr_pct_build_s 1 + #define core_config_bcr_pct_build_i 0 + #define core_config_bcr_pct_build_c 8 + #define core_config_bcr_cc_build 0x006f0004 + #define core_config_bcr_cc_build_version 4 + #define core_config_bcr_cc_build_cc 111 + #define core_config_bcr_ifqueue_build 0x00000002 + #define core_config_bcr_ifqueue_build_bd 0 + #define core_config_bcr_ifqueue_build_version 2 + #define core_config_bcr_smart_build 0x00002003 + #define core_config_bcr_smart_build_version 3 + #define core_config_bcr_smart_build_stack_size 8 + #define core_config_cir_aux_iccm 0x00000000 + #define core_config_cir_dmp_peripheral 0xf0000000 + #define core_config_cir_xccm_base 0xc0000000 + #define core_config_cir_yccm_base 0xe0000000 + #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 2 + #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_complex 1 + #define core_config_dsp_divsqrt "radix2" + #define core_config_dsp_divsqrt_radix2 1 + #define core_config_dsp_itu 1 + #define core_config_dsp_accshift "full" + #define core_config_dsp_accshift_full 1 + #define core_config_agu_large 1 + #define core_config_agu_wb_depth 4 + #define core_config_agu_accord 1 + #define core_config_xy 1 + #define core_config_xy_config "dccm_x_y" + #define core_config_xy_config_dccm_x_y 1 + #define core_config_xy_size 8192 + #define core_config_xy_size_KM "8K" + #define core_config_xy_interleave 1 + #define core_config_xy_x_base 0xc0000000 + #define core_config_xy_y_base 0xe0000000 + #define core_config_bitstream 1 + #define core_config_fpus_div 1 + #define core_config_fpu_mac 1 + #define core_config_fpus_mpy_slow 1 + #define core_config_fpus_div_slow 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_action_points 2 + #define core_config_stack_check 1 + #define core_config_smart_stack_entries 8 + #define core_config_ifq_present 1 + #define core_config_ifq_entries 1 + #define core_config_interrupts_present 1 + #define core_config_interrupts_number 20 + #define core_config_interrupts_priorities 4 + #define core_config_interrupts_externals 16 + #define core_config_interrupts 20 + #define core_config_interrupt_priorities 4 + #define core_config_ext_interrupts 16 + #define core_config_interrupts_firq 1 + #define core_config_interrupts_base 0x0 + #define core_config_dccm_present 1 + #define core_config_dccm_size 0x20000 + #define core_config_dccm_base 0x80000000 + #define core_config_dccm_interleave 1 + #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_pct_counters 8 + #define core_config_dmac 1 + #define core_config_dmac_channels 2 + #define core_config_dmac_registers 0 + #define core_config_dmac_fifo_depth 2 + #define core_config_dmac_int_config "single_internal" + #define core_config_clock_speed 20 +#endif /* __core_config_h */ + diff --git a/bsp/synopsys/emsk_em9d/drivers/board.c b/bsp/synopsys/emsk_em9d/drivers/board.c new file mode 100644 index 0000000000..449360f3a5 --- /dev/null +++ b/bsp/synopsys/emsk_em9d/drivers/board.c @@ -0,0 +1,283 @@ +/* + * Copyright (c) 2018, Synopsys, Inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include + +#include +#include + +#include "board.h" +#include "inc/arc/arc_timer.h" +#include "inc/arc/arc_exception.h" + +#include "inc/embARC_error.h" +#include "mux.h" +#include "dw_uart_obj.h" + + +static void rt_hw_timer_isr(int vector, void *param) +{ + arc_timer_int_clear(BOARD_OS_TIMER_ID); + rt_tick_increase(); +} + +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, 0xe4); +} + +static struct rt_serial_device _emsk_uart0; //abstracted serial for RTT +static struct rt_serial_device _emsk_uart1; + +static rt_err_t _configure(struct rt_serial_device *serial, struct serial_configure *cfg) +{ + DEV_UART_PTR uart; + unsigned int id; + int ret; + + id = (unsigned int)(serial->parent.user_data); + + uart = uart_get_dev(id); + + ret = uart->uart_control(UART_CMD_SET_BAUD, (void *)(cfg->baud_rate)); + + if (ret != E_OK) { + return RT_ERROR; + } + + + return RT_EOK; +} + +static rt_err_t _control(struct rt_serial_device *serial, int cmd, void *arg) +{ + DEV_UART_PTR uart; + unsigned int id; + + id = (unsigned int)(serial->parent.user_data); + uart = uart_get_dev(id); + + switch (cmd) { + case RT_DEVICE_CTRL_CLR_INT: + uart->uart_control(UART_CMD_SET_RXINT, (void *)0); + break; + case RT_DEVICE_CTRL_SET_INT: + uart->uart_control(UART_CMD_SET_RXINT, (void *)1); + break; + case RT_DEVICE_CTRL_SUSPEND: + uart->uart_control(UART_CMD_DIS_DEV, (void *)0); + break; + case RT_DEVICE_CTRL_RESUME: + uart->uart_control(UART_CMD_ENA_DEV, (void *)0); + break; + + default: + return RT_ERROR; + break; + } + + return RT_EOK; +} + +static int _putc(struct rt_serial_device *serial, char c) +{ + DEV_UART_PTR uart; + unsigned int id; + int ret; + + id = (unsigned int)(serial->parent.user_data); + + uart = uart_get_dev(id); + + ret = uart->uart_write(&c, 1); + + if (ret < 0) { + return -1; + } else { + return 1; + } +} + +static int _getc(struct rt_serial_device *serial) +{ + DEV_UART_PTR uart; + unsigned int id; + unsigned int data; + int ret; + int rd_avail = 0; + + id = (unsigned int)(serial->parent.user_data); + uart = uart_get_dev(id); + + uart->uart_control(UART_CMD_GET_RXAVAIL, (void *)(&rd_avail)); + + if (rd_avail > 0) { + ret = uart->uart_read(&data, 1); + } else { + return -1; + } + + if (ret < 0) { + return -1; + } else { + return data; + } + +} + +static void _emsk_uart0_isr(void *ptr) +{ + rt_hw_serial_isr((struct rt_serial_device*)&_emsk_uart0, RT_SERIAL_EVENT_RX_IND); +} + +static const struct rt_uart_ops _emsk_uart0_ops = +{ + _configure, + _control, + _putc, + _getc, +}; + +static void _emsk_uart1_isr(void *ptr) +{ + rt_hw_serial_isr((struct rt_serial_device*)&_emsk_uart1, RT_SERIAL_EVENT_RX_IND); +} + +static const struct rt_uart_ops _emsk_uart1_ops = +{ + _configure, + _control, + _putc, + _getc, +}; + +int rt_hw_uart_init(void) +{ + DEV_UART_PTR uart; + struct serial_configure config; + int ret; + + config.baud_rate = BAUD_RATE_115200; + config.bit_order = BIT_ORDER_LSB; + config.data_bits = DATA_BITS_8; + config.parity = PARITY_NONE; + config.stop_bits = STOP_BITS_1; + config.invert = NRZ_NORMAL; + config.bufsz = RT_SERIAL_RB_BUFSZ; + + _emsk_uart0.ops = &_emsk_uart0_ops; + _emsk_uart0.config = config; + + _emsk_uart1.ops = &_emsk_uart1_ops; + _emsk_uart1.config = config; + + /* open UART1 for USB-UART interface */ + uart = uart_get_dev(DW_UART_1_ID); + /* default format: 8bits, no parity, 1 stop bits */ + ret = uart->uart_open(config.baud_rate); + + if (ret != E_OPNED && ret != E_OK) { + return RT_ERROR; + } + + /* enable rx int */ + uart->uart_control(UART_CMD_SET_RXINT, (void *)1); + /* use customized int isr */ + uart->uart_control(UART_CMD_SET_RXCB, _emsk_uart1_isr); + uart->uart_control(UART_CMD_SET_RXINT_BUF, NULL); + + rt_hw_serial_register(&_emsk_uart1, "uart1", + RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX | RT_DEVICE_FLAG_STREAM, + (void *)DW_UART_1_ID); + + /* open UART0 in PMOD A*/ + uart = uart_get_dev(DW_UART_0_ID); + /* default format: 8bits, no parity, 1 stop bits */ + ret = uart->uart_open(config.baud_rate); + + if (ret != E_OPNED && ret != E_OK) { + return RT_ERROR; + } + + /* enable rx int */ + uart->uart_control(UART_CMD_SET_RXINT, (void *)1); + /* use customized int isr */ + uart->uart_control(UART_CMD_SET_RXCB, _emsk_uart0_isr); + uart->uart_control(UART_CMD_SET_RXINT_BUF, NULL); + + rt_hw_serial_register(&_emsk_uart0, "uart0", + RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX | RT_DEVICE_FLAG_STREAM, + (void *)DW_UART_0_ID); + + return RT_EOK; +} + +void rt_hw_console_output(const char *str) +{ + while(*str != '\0') + { + if (*str == '\n') { + _putc(&_emsk_uart1,'\r'); + } + _putc(&_emsk_uart1,*str); + str++; + } +} + +int rt_hw_timer_init(void) +{ + + unsigned int cyc = BOARD_CPU_CLOCK / RT_TICK_PER_SECOND; + + int_disable(BOARD_OS_TIMER_INTNO); /* disable os timer interrupt */ + arc_timer_stop(BOARD_OS_TIMER_ID); + arc_timer_start(BOARD_OS_TIMER_ID, TIMER_CTRL_IE | TIMER_CTRL_NH, cyc); + + int_handler_install(BOARD_OS_TIMER_INTNO, (INT_HANDLER)rt_hw_timer_isr); + int_enable(BOARD_OS_TIMER_INTNO); + + return 0; +} +INIT_BOARD_EXPORT(rt_hw_timer_init); + +void rt_hw_board_init() +{ + emsk_mux_init(); + + rt_hw_uart_init(); + rt_components_board_init(); + rt_console_set_device(RT_CONSOLE_DEVICE_NAME); +} diff --git a/bsp/synopsys/emsk_em9d/drivers/board.h b/bsp/synopsys/emsk_em9d/drivers/board.h new file mode 100644 index 0000000000..aebf88bd42 --- /dev/null +++ b/bsp/synopsys/emsk_em9d/drivers/board.h @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2018, Synopsys, Inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef __BOARD_H__ +#define __BOARD_H__ + +#include "emsk_hardware.h" + +#define BOARD_OS_TIMER_ID 0 +#define BOARD_OS_TIMER_INTNO 16 +#define BOARD_CPU_CLOCK 25000000 + +#if defined(__GNUC__) +extern int __start_heap; +#define HEAP_BEGIN ((void*)&__start_heap) +#endif + +extern int __end_heap; +#define HEAP_END (void*)(&__end_heap) + +void rt_hw_board_init(); + +int rt_hw_uart_init(void); + +#endif diff --git a/bsp/synopsys/emsk_em9d/drivers/dw_gpio_obj.c b/bsp/synopsys/emsk_em9d/drivers/dw_gpio_obj.c new file mode 100644 index 0000000000..8701a0e9c7 --- /dev/null +++ b/bsp/synopsys/emsk_em9d/drivers/dw_gpio_obj.c @@ -0,0 +1,324 @@ +/* + * Copyright (c) 2018, Synopsys, Inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include "inc/arc/arc.h" +#include "inc/arc/arc_builtin.h" + +#include "dw_gpio_obj.h" + +#include "emsk_hardware.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 +} diff --git a/bsp/synopsys/emsk_em9d/drivers/dw_gpio_obj.h b/bsp/synopsys/emsk_em9d/drivers/dw_gpio_obj.h new file mode 100644 index 0000000000..d39a09159d --- /dev/null +++ b/bsp/synopsys/emsk_em9d/drivers/dw_gpio_obj.h @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2018, Synopsys, Inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ +#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_*/ diff --git a/bsp/synopsys/emsk_em9d/drivers/dw_uart_obj.c b/bsp/synopsys/emsk_em9d/drivers/dw_uart_obj.c new file mode 100644 index 0000000000..9e3ebd3db9 --- /dev/null +++ b/bsp/synopsys/emsk_em9d/drivers/dw_uart_obj.c @@ -0,0 +1,210 @@ +/* + * Copyright (c) 2018, Synopsys, Inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ +#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 "dw_uart_obj.h" + +#include "emsk_hardware.h" + +#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 +} diff --git a/bsp/synopsys/emsk_em9d/drivers/dw_uart_obj.h b/bsp/synopsys/emsk_em9d/drivers/dw_uart_obj.h new file mode 100644 index 0000000000..7a63880fab --- /dev/null +++ b/bsp/synopsys/emsk_em9d/drivers/dw_uart_obj.h @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2018, Synopsys, Inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ +#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/bsp/synopsys/emsk_em9d/drivers/embARC_BSP_config.h b/bsp/synopsys/emsk_em9d/drivers/embARC_BSP_config.h new file mode 100644 index 0000000000..706aac94c4 --- /dev/null +++ b/bsp/synopsys/emsk_em9d/drivers/embARC_BSP_config.h @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2018, Synopsys, Inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#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 (4 * 1024) +#define _HEAPSZ (32 * 1024) + + + +#ifdef __cplusplus +} +#endif + +#endif /* _EMBARC_CONFIG_BSP_H_ */ diff --git a/bsp/synopsys/emsk_em9d/drivers/emsk_hardware.h b/bsp/synopsys/emsk_em9d/drivers/emsk_hardware.h new file mode 100644 index 0000000000..d60e314389 --- /dev/null +++ b/bsp/synopsys/emsk_em9d/drivers/emsk_hardware.h @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2018, Synopsys, Inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ +#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 + +#ifdef ARC_FEATURE_DMP_PERIPHERAL +#define PERIPHERAL_BASE ARC_FEATURE_DMP_PERIPHERAL +#else +#define PERIPHERAL_BASE _arc_aux_read(AUX_DMP_PERIPHERAL) +#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_ */ diff --git a/bsp/synopsys/emsk_em9d/drivers/mux.c b/bsp/synopsys/emsk_em9d/drivers/mux.c new file mode 100644 index 0000000000..a56cb15212 --- /dev/null +++ b/bsp/synopsys/emsk_em9d/drivers/mux.c @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2018, Synopsys, Inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include "mux_hal.h" +#include "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]; +} diff --git a/bsp/synopsys/emsk_em9d/drivers/mux.h b/bsp/synopsys/emsk_em9d/drivers/mux.h new file mode 100644 index 0000000000..47f796bebe --- /dev/null +++ b/bsp/synopsys/emsk_em9d/drivers/mux.h @@ -0,0 +1,147 @@ +/* + * Copyright (c) 2018, Synopsys, Inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ +#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_ */ diff --git a/bsp/synopsys/emsk_em9d/drivers/mux_hal.h b/bsp/synopsys/emsk_em9d/drivers/mux_hal.h new file mode 100644 index 0000000000..9a5c8c14b9 --- /dev/null +++ b/bsp/synopsys/emsk_em9d/drivers/mux_hal.h @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2018, Synopsys, Inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ +#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_ */ diff --git a/bsp/synopsys/emsk_em9d/emsk_em9d.ld b/bsp/synopsys/emsk_em9d/emsk_em9d.ld new file mode 100644 index 0000000000..849ecf6329 --- /dev/null +++ b/bsp/synopsys/emsk_em9d/emsk_em9d.ld @@ -0,0 +1,114 @@ +MEMORY +{ + ICCM : ORIGIN = 0x00000000, LENGTH = 0x40000 + DCCM : ORIGIN = 0x80000000, LENGTH = 0x20000 + EXT_RAM : ORIGIN = 0x10000000, LENGTH = 0x8000000 +} +ENTRY(_start) +SECTIONS +{ + .init : + { + _f_init = .; + KEEP (*(.init_vector)) + KEEP (*(.init_bootstrap)) + _e_init = .; + } > EXT_RAM + .vector : ALIGN(1024) + { + _f_vector = .; + *(.vector) + _e_vector = .; + } > EXT_RAM + .text : ALIGN(4) + { + _f_text = .; + *(.text .text.* .gnu.linkonce.t.*) + _e_text = .; + } > EXT_RAM + .rodata : ALIGN(4) + { + _f_rodata = .; + + /* section information for finsh shell */ + . = ALIGN(4); + __fsymtab_start = .; + KEEP(*(FSymTab)) + __fsymtab_end = .; + . = ALIGN(4); + __vsymtab_start = .; + KEEP(*(VSymTab)) + __vsymtab_end = .; + + . = ALIGN(4); + __rt_init_start = .; + KEEP(*(SORT(.rti_fn*))) + __rt_init_end = .; + . = 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 = .; + } > EXT_RAM + .data : ALIGN(4) + { + _f_data = .; + *(.data .data.* .gnu.linkonce.d.*) + _f_sdata = .; + __SDATA_BEGIN__ = .; + *(.sdata .sdata.* .gnu.linkonce.s.*) + _e_sdata = .; + _e_data = .; + } > EXT_RAM + .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 = .; + } > EXT_RAM + .stack (NOLOAD) : + { + . = ALIGN(4); + _f_stack = .; + . = . + 4096; + _e_stack = .; + } > EXT_RAM + .heap (NOLOAD) : + { + . = ALIGN(4); + __start_heap = . ; + _f_heap = .; + . = . + 0x8000; + _e_heap = .; + __end_heap = . ; + } > EXT_RAM + _load_addr_text = LOADADDR(.text); + _load_addr_rodata = LOADADDR(.rodata); + _load_addr_data = LOADADDR(.data); +} diff --git a/bsp/synopsys/emsk_em9d/openocd.log b/bsp/synopsys/emsk_em9d/openocd.log new file mode 100644 index 0000000000..4ef893515e --- /dev/null +++ b/bsp/synopsys/emsk_em9d/openocd.log @@ -0,0 +1,9 @@ +Warn : deprecated option: -p/--pipe. Use '-c "gdb_port pipe; log_output openocd.log"' instead. +adapter speed: 5000 kHz +Error: libusb_open() failed with LIBUSB_ERROR_NOT_SUPPORTED +Info : clock speed 5000 kHz +Info : JTAG tap: arc-em.cpu tap/device found: 0x200044b1 (mfg: 0x258, part: 0x0004, ver: 0x2) +Info : JTAG tap: arc-em.cpu tap/device found: 0x200044b1 (mfg: 0x258, part: 0x0004, ver: 0x2) +target state: halted +Info : accepting 'gdb' connection from pipe +Info : dropped 'gdb' connection diff --git a/bsp/synopsys/emsk_em9d/rtconfig.h b/bsp/synopsys/emsk_em9d/rtconfig.h new file mode 100644 index 0000000000..865e753ae5 --- /dev/null +++ b/bsp/synopsys/emsk_em9d/rtconfig.h @@ -0,0 +1,142 @@ +/* RT-Thread config file */ +#ifndef __RTTHREAD_CFG_H__ +#define __RTTHREAD_CFG_H__ + +// + +// +#define RT_NAME_MAX 6 +// +#define RT_ALIGN_SIZE 4 +// +// 8 +// 32 +// 256 +// +#define RT_THREAD_PRIORITY_MAX 32 +// +#define RT_TICK_PER_SECOND 1000 +// +#define IDLE_THREAD_STACK_SIZE 512 +//
+#define RT_DEBUG +// +// #define RT_THREAD_DEBUG +// +#define RT_USING_OVERFLOW_CHECK +//
+ +// +#define RT_USING_HOOK +//
+// #define RT_USING_TIMER_SOFT +// +#define RT_TIMER_THREAD_PRIO 4 +// +#define RT_TIMER_THREAD_STACK_SIZE 512 +// +#define RT_TIMER_TICK_PER_SECOND 10 +//
+ +//
+// +#define RT_USING_SEMAPHORE +// +#define RT_USING_MUTEX +// +#define RT_USING_EVENT +// +#define RT_USING_MAILBOX +// +#define RT_USING_MESSAGEQUEUE +//
+ +//
+// +#define RT_USING_MEMPOOL +// +// #define RT_USING_MEMHEAP +// +#define RT_USING_HEAP +// +// #define RT_USING_MEMHEAP_AS_HEAP +// +#define RT_USING_SMALL_MEM +// +// #define RT_USING_SLAB +//
+ +//
+#define RT_USING_DEVICE +// +#define RT_USING_DEVICE_IPC +// +#define RT_USING_SERIAL +// +#define RT_UART_RX_BUFFER_SIZE 64 +// +#define RT_USING_INTERRUPT_INFO +//
+ +//
+#define RT_USING_CONSOLE +// +#define RT_CONSOLEBUF_SIZE 128 +// +#define RT_CONSOLE_DEVICE_NAME "uart1" +//
+ +// +#define RT_USING_COMPONENTS_INIT +//
+#define RT_USING_FINSH +// +#define FINSH_USING_MSH +// +#define FINSH_USING_MSH_DEFAULT +// +#define FINSH_USING_SYMTAB +// +#define FINSH_USING_DESCRIPTION +// +#define FINSH_THREAD_STACK_SIZE 4096 +//
+ +//
+// +// +#define RT_USING_PTHREADS +//
+ +//
+// #define RT_USING_DFS +// +// #define DFS_USING_WORKDIR +// +#define DFS_FILESYSTEMS_MAX 2 +// +#define DFS_FD_MAX 4 +// +#define RT_USING_DFS_ELMFAT +// +// 1 +// 2 +// +#define RT_DFS_ELM_USE_LFN 1 +// +#define RT_DFS_ELM_MAX_LFN 64 +// +// #define RT_USING_DFS_YAFFS2 +// +// #define RT_USING_DFS_UFFS +// +// #define RT_USING_DFS_DEVFS +// +// #define RT_USING_DFS_NFS +// +#define RT_NFS_HOST_EXPORT "192.168.1.5:/" +//
+//
+ + +#endif diff --git a/bsp/synopsys/emsk_em9d/rtconfig.py b/bsp/synopsys/emsk_em9d/rtconfig.py new file mode 100644 index 0000000000..7ba12867fd --- /dev/null +++ b/bsp/synopsys/emsk_em9d/rtconfig.py @@ -0,0 +1,60 @@ +import os + +# toolchains options +ARCH='arc' +CPU='em' +CROSS_TOOL='gcc' + +if os.getenv('RTT_CC'): + CROSS_TOOL = os.getenv('RTT_CC') + +# only support GNU GCC compiler +PLATFORM = 'gcc' +EXEC_PATH = 'C:/arc/gnu/bin' + +if os.getenv('RTT_EXEC_PATH'): + EXEC_PATH = os.getenv('RTT_EXEC_PATH') + +BUILD = 'debug' + +if PLATFORM == 'gcc': + # toolchains + PREFIX = 'arc-elf32-' + CC = PREFIX + 'gcc' + CXX = PREFIX + 'g++' + AS = PREFIX + 'gcc' + AR = PREFIX + 'ar' + LINK = PREFIX + 'gcc' + TARGET_EXT = 'elf' + SIZE = PREFIX + 'size' + OBJDUMP = PREFIX + 'objdump' + OBJCPY = PREFIX + 'objcopy' + DBG = PREFIX + 'gdb' + DEVICE = ' -mno-sdata -Wall -mcpu=em4_fpus -mlittle-endian -mcode-density -mdiv-rem -mswap -mnorm -mmpy-option=6 -mbarrel-shifter -mfpu=fpus_all' + CFLAGS = DEVICE + AFLAGS = ' -c' + DEVICE + ' -x assembler-with-cpp' + LINK_SCRIPT = 'emsk_em9d.ld' + LFLAGS = DEVICE + ' -mno-sdata -nostartfiles -Wl,--gc-sections,-Map=emsk_em9d.map,-cref,-u,system_vectors -T %s' % LINK_SCRIPT + + OPENOCD_SCRIPT_ROOT = 'C:/arc/gnu/share/openocd/scripts' + OPENOCD_CFG_FILE = OPENOCD_SCRIPT_ROOT + '/board/snps_em_sk_v2.2.cfg' + + OPENOCD_OPTIONS = '-s %s -f %s' % (OPENOCD_SCRIPT_ROOT, OPENOCD_CFG_FILE) + + DBG_HW_FLAGS = ''' -ex "target remote | openocd --pipe %s" -ex "load" ''' % OPENOCD_OPTIONS + + + TARGET = 'rtthread_snps_emsk_em9d.' + TARGET_EXT + + CPATH = '' + LPATH = '' + + if BUILD == 'debug': + CFLAGS += ' -O0 -gdwarf-2' + AFLAGS += ' -gdwarf-2' + else: + CFLAGS += ' -O2' + + POST_ACTION = OBJCPY + ' -O binary $TARGET rtthread.bin\n' +\ + SIZE + ' $TARGET \n' + #POST_ACTION = DBG + DBG_HW_FLAGS + TARGET diff --git a/libcpu/arc/SConscript b/libcpu/arc/SConscript new file mode 100644 index 0000000000..cbec0b5ec1 --- /dev/null +++ b/libcpu/arc/SConscript @@ -0,0 +1,17 @@ +# RT-Thread building script for bridge + +import os +from building import * + +Import('rtconfig') + +cwd = GetCurrentDir() +group = [] + +# add common code files +group = group + SConscript(os.path.join(cwd, 'common', 'SConscript')) + +# cpu porting code files +group = group + SConscript(os.path.join(cwd, rtconfig.CPU, 'SConscript')) + +Return('group') diff --git a/libcpu/arc/common/SConscript b/libcpu/arc/common/SConscript new file mode 100644 index 0000000000..1c77347e61 --- /dev/null +++ b/libcpu/arc/common/SConscript @@ -0,0 +1,10 @@ +from building import * + +cwd = GetCurrentDir() +src = Glob('*.c') +CPPPATH = [cwd] + + +group = DefineGroup('cpu', src, depend = [], CPPPATH = CPPPATH) + +Return('group') diff --git a/libcpu/arc/em/SConscript b/libcpu/arc/em/SConscript new file mode 100644 index 0000000000..49c32b689d --- /dev/null +++ b/libcpu/arc/em/SConscript @@ -0,0 +1,17 @@ +# RT-Thread building script for component + +from building import * + +Import('rtconfig') + +cwd = GetCurrentDir() +src = Glob('*.c') +CPPPATH = [cwd] + + +if rtconfig.PLATFORM == 'gcc': + src += Glob('*_gcc.S') + +group = DefineGroup('cpu', src, depend = [''], CPPPATH = CPPPATH) + +Return('group') diff --git a/libcpu/arc/em/contex_gcc.S b/libcpu/arc/em/contex_gcc.S new file mode 100644 index 0000000000..a8abe089bf --- /dev/null +++ b/libcpu/arc/em/contex_gcc.S @@ -0,0 +1,266 @@ +/* + * Copyright (c) 2018, Synopsys, Inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ +#define __ASSEMBLY__ +#include "inc/arc/arc.h" +#include "inc/arc/arc_asm_common.h" + +.global rt_interrupt_enter; .type rt_interrupt_enter, %function +.global rt_interrupt_leave; .type rt_interrupt_leave, %function +.global context_switch_reqflg; .type context_switch_reqflg, %object +.global rt_interrupt_from_thread; .type rt_interrupt_from_thread, %object +.global rt_interrupt_to_thread; .type rt_interrupt_to_thread, %object + + .text + .align 4 +dispatcher: + st sp, [r0] + ld sp, [r1] + pop r0 + j [r0] + +/* return routine when task dispatch happened in task context */ +dispatch_r: + RESTORE_NONSCRATCH_REGS + j [blink] + +/* + * rt_base_t rt_hw_interrupt_disable(); + */ +.global rt_hw_interrupt_disable +.type rt_hw_interrupt_disable, %function +rt_hw_interrupt_disable: + clri r0 + j [blink] + + +/* + * void rt_hw_interrupt_enable(rt_base_t level); + */ +.global rt_hw_interrupt_enable +.type rt_hw_interrupt_enable, %function +rt_hw_interrupt_enable: + seti r0 + j [blink] + + +.global rt_hw_context_switch_interrupt +.type rt_hw_context_switch_interrupt, %function +rt_hw_context_switch_interrupt: + st r0, [rt_interrupt_from_thread] + st r1, [rt_interrupt_to_thread] + mov r0, 1 + st r0, [context_switch_reqflg] + j [blink] + + +/* + * void rt_hw_context_switch(rt_uint32 from, rt_uint32 to); + * r0 --> from + * r1 --> to + */ +.global rt_hw_context_switch +.type rt_hw_context_switch, %function +rt_hw_context_switch: + SAVE_NONSCRATCH_REGS + mov r2, dispatch_r + push r2 + b dispatcher + + +/* + * void rt_hw_context_switch_to(rt_uint32 to); + * r0 --> to + */ +.global rt_hw_context_switch_to +.type rt_hw_context_switch_to, %function +rt_hw_context_switch_to: + ld sp, [r0] + pop r0 + j [r0] + +.global start_r +.type start_r, %function +start_r: + pop blink; + pop r1 + pop r2 + pop r0 + + j_s.d [r1] + kflag r2 + +/****** exceptions and interrupts handing ******/ +/****** entry for exception handling ******/ + .global exc_entry_cpu + .align 4 +exc_entry_cpu: + + EXCEPTION_PROLOGUE + + mov blink, sp + mov r3, sp /* as exception handler's para(p_excinfo) */ + + ld r0, [exc_nest_count] + add r1, r0, 1 + st r1, [exc_nest_count] + cmp r0, 0 + bne exc_handler_1 +/* change to exception stack if interrupt happened in task context */ + mov sp, _e_stack +exc_handler_1: + PUSH blink + + lr r0, [AUX_ECR] + lsr r0, r0, 16 + mov r1, exc_int_handler_table + ld.as r2, [r1, r0] + + mov r0, r3 + jl [r2] + +/* interrupts are not allowed */ +ret_exc: + POP sp + mov r1, exc_nest_count + ld r0, [r1] + sub r0, r0, 1 + cmp r0, 0 + bne.d ret_exc_1 + st r0, [r1] + + ld r0, [context_switch_reqflg] + cmp r0, 0 + bne ret_exc_2 +ret_exc_1: /* return from non-task context, interrupts or exceptions are nested */ + EXCEPTION_EPILOGUE + rtie + +/* there is a dispatch request */ +ret_exc_2: + /* clear dispatch request */ + mov r0, 0 + st r0, [context_switch_reqflg] + + SAVE_CALLEE_REGS /* save callee save registers */ + + /* clear exception bit to do exception exit by SW */ + lr r0, [AUX_STATUS32] + bclr r0, r0, AUX_STATUS_BIT_AE + kflag r0 + + mov r1, ret_exc_r /* save return address */ + PUSH r1 + + ld r0, [rt_interrupt_from_thread] + ld r1, [rt_interrupt_to_thread] + b dispatcher + +ret_exc_r: + /* recover exception status */ + lr r0, [AUX_STATUS32] + bset r0, r0, AUX_STATUS_BIT_AE + kflag r0 + + RESTORE_CALLEE_REGS + EXCEPTION_EPILOGUE + rtie + +/****** entry for normal interrupt exception handling ******/ + .global exc_entry_int /* entry for interrupt handling */ + .align 4 +exc_entry_int: +#if ARC_FEATURE_FIRQ == 1 +/* check whether it is P0 interrupt */ +#if ARC_FEATURE_RGF_NUM_BANKS > 1 + lr r0, [AUX_IRQ_ACT] + btst r0, 0 + jnz exc_entry_firq +#else + PUSH r10 + lr r10, [AUX_IRQ_ACT] + btst r10, 0 + POP r10 + jnz exc_entry_firq +#endif +#endif + INTERRUPT_PROLOGUE + + mov blink, sp + + clri /* disable interrupt */ + ld r3, [exc_nest_count] + add r2, r3, 1 + st r2, [exc_nest_count] + seti /* enable higher priority interrupt */ + + cmp r3, 0 + bne irq_handler_1 +/* change to exception stack if interrupt happened in task context */ + mov sp, _e_stack +irq_handler_1: + PUSH blink + + jl rt_interrupt_enter + + lr r0, [AUX_IRQ_CAUSE] + sr r0, [AUX_IRQ_SELECT] + mov r1, exc_int_handler_table + ld.as r2, [r1, r0] /* r2 = exc_int_handler_table + irqno *4 */ +/* 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: + lr r3, [AUX_IRQ_PRIORITY] + PUSH r3 /* save irq priority */ + + jl [r2] /* jump to interrupt handler */ + jl rt_interrupt_leave +ret_int: + clri /* disable interrupt */ + POP r3 /* irq priority */ + POP sp + mov r1, exc_nest_count + ld r0, [r1] + sub r0, r0, 1 + cmp r0, 0 + bne.d ret_int_1 + st r0, [r1] + + ld r0, [context_switch_reqflg] + cmp r0, 0 + bne ret_int_2 +ret_int_1: /* return from non-task context */ + INTERRUPT_EPILOGUE + rtie +/* there is a dispatch request */ +ret_int_2: + /* clear dispatch request */ + mov r0, 0 + st r0, [context_switch_reqflg] + + /* interrupt return by SW */ + lr r10, [AUX_IRQ_ACT] + PUSH r10 + bclr r10, r10, r3 /* clear related bits in IRQ_ACT */ + sr r10, [AUX_IRQ_ACT] + + SAVE_CALLEE_REGS /* save callee save registers */ + mov r1, ret_int_r /* save return address */ + PUSH r1 + + ld r0, [rt_interrupt_from_thread] + ld r1, [rt_interrupt_to_thread] + b dispatcher + +ret_int_r: + RESTORE_CALLEE_REGS + /* recover AUX_IRQ_ACT to restore the interrup status */ + POPAX AUX_IRQ_ACT + INTERRUPT_EPILOGUE + rtie \ No newline at end of file diff --git a/libcpu/arc/em/cpuport.c b/libcpu/arc/em/cpuport.c new file mode 100644 index 0000000000..88c2e12f9b --- /dev/null +++ b/libcpu/arc/em/cpuport.c @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2018, Synopsys, Inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include + +#include "inc/arc/arc_exception.h" + +/* enable interrupt and set interrupt priority mask */ +#define ARC_INIT_STATUS (AUX_STATUS_MASK_IE | ((-1 - INT_PRI_MIN) << 1)) + + +extern void start_r(void); + + +rt_uint32_t context_switch_reqflg; +rt_uint32_t rt_interrupt_from_thread; +rt_uint32_t rt_interrupt_to_thread; + +struct init_stack_frame { + rt_uint32_t pc; + rt_uint32_t blink; + rt_uint32_t task; + rt_uint32_t status32; + rt_uint32_t r0; +}; + +/** + * shutdown CPU + */ +void rt_hw_cpu_shutdown(void) +{ + +} + +rt_uint8_t *rt_hw_stack_init(void *tentry, + void *parameter, + rt_uint8_t *stack_addr, + void *texit) +{ + struct init_stack_frame *stack_frame; + rt_uint8_t *stk; + + stk = stack_addr + sizeof(rt_uint32_t); + stk = (rt_uint8_t *)RT_ALIGN_DOWN((rt_uint32_t)stk, 8); + stk -= sizeof(struct init_stack_frame); + + stack_frame = (struct init_stack_frame *)stk; + + stack_frame->pc = (rt_uint32_t)start_r; + stack_frame->blink = (rt_uint32_t)texit; + stack_frame->task = (rt_uint32_t)tentry; + stack_frame->status32 = ARC_INIT_STATUS; + stack_frame->r0 = (rt_uint32_t)parameter; + + return stk; +} + + +/** + * This function set the hook, which is invoked on fault exception handling. + * + * @param exception_handle the exception handling hook function. + */ +void rt_hw_exception_install(rt_err_t (*exception_handle)(void *context)) +{ + exception_handle = exception_handle; +} \ No newline at end of file