arch: arc: update the ARC port

* add basic synopsys arc em processor support
* add basic arc nsim em virtual board support
* add basic arc mwdt toolchain support

Signed-off-by: Watson Zeng <zhiwei@synopsys.com>
This commit is contained in:
Watson Zeng
2020-03-25 17:11:52 +08:00
committed by Jingru
parent 13eaef3d46
commit 0d4593ee5e
169 changed files with 871 additions and 46371 deletions

View File

@@ -273,6 +273,8 @@ __PORT__ void port_cpsr_restore(cpu_cpsr_t cpsr);
__PORT__ void port_cpu_reset(void);
__PORT__ uint32_t port_cpu_clz(uint32_t);
__PORT__ void port_sched_start(void) __NO_RETURN__;
__PORT__ void port_context_switch(void);

View File

@@ -52,7 +52,7 @@ __PORT__ void port_cpu_reset(void)
__PORT__ void port_systick_config(uint32_t cycle_per_tick) // Configure SysTick to generate an interrupt every cycle_per_tick
{
timer_int_clear(0); // nsim #define BOARD_SYS_TIMER_ID TIMER_0
arc_timer_int_clear(0); // nsim #define BOARD_SYS_TIMER_ID TIMER_0
board_timer_update(cycle_per_tick); // board.c
}
__PORT__ void port_systick_priority_set(uint32_t prio) // Sets the int priority

View File

@@ -21,15 +21,10 @@
#define TOS_CFG_CPU_ADDR_SIZE CPU_WORD_SIZE_32
#define TOS_CFG_CPU_DATA_SIZE CPU_WORD_SIZE_32
#define TOS_CFG_CPU_STK_GROWTH CPU_STK_GROWTH_DESCENDING
// #define TOS_CFG_CPU_HRTIMER_SIZE CPU_WORD_SIZE_32
#define TOS_CFG_CPU_HRTIMER_EN 0u
#define TOS_CFG_CPU_LEAD_ZEROS_ASM_PRESENT 1u
#define TOS_CFG_CPU_HRTIMER_EN 0u
#define TOS_CFG_CPU_LEAD_ZEROS_ASM_PRESENT 0u
#if (defined(__VFP_FP__) && !defined(__SOFTFP__))
#define TOS_CFG_CPU_ARM_FPU_EN 1u
#else
#define TOS_CFG_CPU_ARM_FPU_EN 0u
#endif
#define TOS_CFG_CPU_ARM_FPU_EN 0u
#endif /* _PORT_CONFIG_H_ */

360
arch/arc/arcem/port_s.s Normal file
View File

@@ -0,0 +1,360 @@
/*
* Copyright (c) 2020, Synopsys, Inc.
*
* SPDX-License-Identifier: Apache-2.0
*/
#define __ASSEMBLY__
#include "arc.h"
#include "arc_asm_common.h"
.global k_curr_task
.global k_next_task
.global g_exc_nest_count
.global g_context_switch_reqflg
.global tos_knl_irq_enter
.global tos_knl_irq_leave
.text
.align 4
dispatcher:
st sp, [r0] // ld r0, [k_curr_task]
ld sp, [r1] // ld r1, [k_next_task]
# k_curr_task = k_next_task;
st r1, [k_curr_task]
pop r0
j [r0]
/* return routine when task dispatch happened in task context */
dispatch_r:
RESTORE_NONSCRATCH_REGS
j [blink]
/*
* void port_int_disable(void);
*/
.global port_int_disable
.align 4
port_int_disable:
clri
j [blink]
/*
* void port_int_enable(void);
*/
.global port_int_enable
.align 4
port_int_enable:
seti
j [blink]
/*
* cpu_cpsr_t port_cpsr_save(void);
*/
.global port_cpsr_save
.align 4
port_cpsr_save:
clri r0
j [blink]
/*
* void port_cpsr_restore(cpu_cpsr_t cpsr);
*/
.global port_cpsr_restore
.align 4
port_cpsr_restore:
seti r0
j [blink]
/*
* uint32_t port_cpu_clz(uint32_t val)
* r0 --> val
*/
.global port_cpu_clz
.align 4
port_cpu_clz:
breq r0, 0, cpu_clz_return
ffs r1, r0
add r0, r1, 1
cpu_clz_return:
j [blink]
/*
* void port_sched_start(void)
*/
.global port_sched_start
.align 4
port_sched_start:
ld r0, [k_curr_task]
ld sp, [r0]
pop r0
j [r0]
/*
* void port_context_switch(void)
*/
.global port_context_switch
.align 4
port_context_switch:
SAVE_NONSCRATCH_REGS
mov r2, dispatch_r
push r2
ld r0, [k_curr_task]
ld r1, [k_next_task]
b dispatcher
/*
* void port_irq_context_switch(void)
*/
.global port_irq_context_switch
.align 4
port_irq_context_switch:
mov r0, 1
st r0, [g_context_switch_reqflg]
j [blink]
/*
* void start_r(void)
*/
.global start_r
.align 4
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, [g_exc_nest_count]
add r1, r0, 1
st r1, [g_exc_nest_count]
brne r0, 0, exc_handler_1
/* change to exception stack if interrupt happened in task context */
mov sp, _e_stack
exc_handler_1:
PUSH blink
jl tos_knl_irq_enter
lr r0, [AUX_ECR]
lsr r0, r0, 16
mov r1, exc_int_handler_table
ld.as r2, [r1, r0]
mov r0, r3
jl [r2]
jl tos_knl_irq_leave
/* interrupts are not allowed */
ret_exc:
POP sp
mov r1, g_exc_nest_count
ld r0, [r1]
sub r0, r0, 1
st r0, [r1]
brne r0, 0, ret_exc_1 /* nest exception case */
lr r1, [AUX_IRQ_ACT] /* nest interrupt case */
brne r1, 0, ret_exc_1
ld r0, [g_context_switch_reqflg]
brne r0, 0, 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, [g_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, [k_curr_task]
ld r1, [k_next_task]
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, [g_exc_nest_count]
add r2, r3, 1
st r2, [g_exc_nest_count]
seti /* enable higher priority interrupt */
brne r3, 0, irq_handler_1
/* change to exception stack if interrupt happened in task context */
mov sp, _e_stack
#if ARC_FEATURE_STACK_CHECK
#if ARC_FEATURE_SEC_PRESENT
lr r0, [AUX_SEC_STAT]
bclr r0, r0, AUX_SEC_STAT_BIT_SSC
sflag r0
#else
lr r0, [AUX_STATUS32]
bclr r0, r0, AUX_STATUS_BIT_SC
kflag r0
#endif
#endif
irq_handler_1:
PUSH blink
jl tos_knl_irq_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 tos_knl_irq_leave
ret_int:
clri /* disable interrupt */
POP r3 /* irq priority */
POP sp
mov r1, g_exc_nest_count
ld r0, [r1]
sub r0, r0, 1
st r0, [r1]
/* if there are multi-bits set in IRQ_ACT, it's still in nest interrupt */
lr r0, [AUX_IRQ_CAUSE]
sr r0, [AUX_IRQ_SELECT]
lr r3, [AUX_IRQ_PRIORITY]
lr r1, [AUX_IRQ_ACT]
bclr r2, r1, r3
brne r2, 0, ret_int_1
ld r0, [g_context_switch_reqflg]
brne r0, 0, 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, [g_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, [k_curr_task]
ld r1, [k_next_task]
b dispatcher
ret_int_r:
RESTORE_CALLEE_REGS
/* recover AUX_IRQ_ACT to restore the interrup status */
POPAX AUX_IRQ_ACT
INTERRUPT_EPILOGUE
rtie
/****** entry for fast irq exception handling ******/
.global exc_entry_firq
.align 4
exc_entry_firq:
SAVE_FIQ_EXC_REGS
jl tos_knl_irq_enter
lr r0, [AUX_IRQ_CAUSE]
mov r1, exc_int_handler_table
/* r2 = _kernel_exc_tbl + irqno *4 */
ld.as r2, [r1, r0]
/* for the case of software triggered interrupt */
lr r3, [AUX_IRQ_HINT]
cmp r3, r0
bne.d firq_hint_handled
xor r3, r3, r3
sr r3, [AUX_IRQ_HINT]
firq_hint_handled:
/* jump to interrupt handler */
mov r0, sp
jl [r2]
jl tos_knl_irq_leave
firq_return:
RESTORE_FIQ_EXC_REGS
rtie

View File

@@ -140,7 +140,7 @@ __KNL__ void cpu_fault_diagnosis(void);
/* Restore CPU status word. */
#define TOS_CPU_INT_ENABLE() \
do { \
__builtin_arc_seti(cpu_cpsr); \
tos_cpu_cpsr_restore(cpu_cpsr); \
} while (0)
#endif /* _TOS_CPU_H_ */

View File

@@ -16,7 +16,13 @@
*---------------------------------------------------------------------------*/
#include <tos_k.h>
#include "arc/arc_exception.h"
#include "embARC.h"
void tos_cup_tick_handler(void)
{
arc_timer_int_clear(BOARD_OS_TIMER_ID);
tos_tick_handler();
}
__API__ uint32_t tos_cpu_clz(uint32_t val)
{
@@ -100,14 +106,18 @@ __KNL__ void cpu_context_switch(void)
__KNL__ void cpu_irq_context_switch(void)
{
// port_irq_context_switch();
// DO NOTHING
port_irq_context_switch();
}
__KNL__ void cpu_systick_init(k_cycle_t cycle_per_tick)
{
port_systick_priority_set(TOS_CFG_CPU_SYSTICK_PRIO);
port_systick_config(cycle_per_tick);
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, cycle_per_tick);
int_handler_install(BOARD_OS_TIMER_INTNO, (INT_HANDLER_T)tos_cup_tick_handler);
int_pri_set(BOARD_OS_TIMER_INTNO, INT_PRI_MIN + 1);
int_enable(BOARD_OS_TIMER_INTNO);
}
#if TOS_CFG_TICKLESS_EN > 0u
@@ -188,7 +198,18 @@ __KNL__ void cpu_standby_mode_enter(void)
}
#endif /* TOS_CFG_PWR_MGR_EN */
uint32_t g_context_switch_reqflg;
uint32_t g_exc_nest_count;
extern void start_r(void);
#if ARC_FEATURE_STACK_CHECK
#define ARC_INIT_STATUS ((1 << AUX_STATUS_BIT_SC) | AUX_STATUS_MASK_IE | ((-1 - INT_PRI_MIN) << 1) | STATUS32_RESET_VALUE)
#else
#define ARC_INIT_STATUS (AUX_STATUS_MASK_IE | ((-1 - INT_PRI_MIN) << 1) | STATUS32_RESET_VALUE)
#endif
__KNL__ k_stack_t *cpu_task_stk_init(void *entry,
void *arg,
void *exit,
@@ -206,7 +227,7 @@ __KNL__ k_stack_t *cpu_task_stk_init(void *entry,
regs->pc = (cpu_data_t)start_r;
regs->blink = (cpu_data_t)exit;
regs->task = (cpu_data_t)entry;
regs->status32 = (cpu_data_t)(AUX_STATUS_MASK_IE | ((-1 - INT_PRI_MIN) << 1) | STATUS32_RESET_VALUE);
regs->status32 = ARC_INIT_STATUS;
regs->r0 = (cpu_data_t)arg;

View File

@@ -1,107 +0,0 @@
.global port_int_disable
.global port_int_enable
.global port_cpsr_save
.global port_cpsr_restore
.global port_sched_start
.global port_context_switch
.global start_r
.extern k_curr_task
.extern k_next_task
.text
.align 4
.type port_int_disable, %function
port_int_disable:
clri
j [blink]
.type port_int_enable, %function
port_int_enable:
seti
j [blink]
.type port_cpsr_save, %function
port_cpsr_save:
clri r0
j [blink]
.type port_cpsr_restore, %function
port_cpsr_restore:
seti r0
j [blink]
.type port_sched_start, %function
port_sched_start:
ld r0, [k_curr_task]
ld r1, [k_next_task]
ld r2, [r1]
st r2, [r0] /*k_curr_task=k_next_task*/
ld r0, [r2]
ld sp, [r0]
pop r3
j [r3]
.type start_r, %function
start_r:
pop blink;
pop r1
pop r2
pop r0
j_s.d [r1]
kflag r2
.type port_context_switch, %function
port_context_switch:
pop r15
pop r14
pop r13
pop blink
pop fp
pop gp
j [blink]
.type PendSV_Handler, %function
TaskSwitchContext:
clri
push gp
push fp
push blink
push r13
push r14
push r15
mov r2, dispatch_r
push r2
mov r5, k_curr_task
ld r6, [r5]
st r0, [r6]
mov r1, k_next_task
ld r2, [r1]
st r2, [r5]
ld r0, [r2]
ld sp, [r0]
seti
j [r0]
dispatch_r:
pop r15
pop r14
pop r13
pop blink
pop fp
pop gp
j [blink]

View File

@@ -1,253 +0,0 @@
#ifndef H_CORE_CONFIG
#define H_CORE_CONFIG
#define core_config_cir_identity 0x00000043
#define core_config_cir_identity_chipid 0
#define core_config_cir_identity_arcnum 0
#define core_config_cir_identity_arcver 67
#define core_config_cir_identity_family 4
#define core_config_cir_identity_corever 3
#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_mpu_build 0x00010002
#define core_config_bcr_mpu_build_i 0
#define core_config_bcr_mpu_build_s 0
#define core_config_bcr_mpu_build_regions 16
#define core_config_bcr_mpu_build_version 2
#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_d_cache_build 0x00215104
#define core_config_bcr_d_cache_build_version 4
#define core_config_bcr_d_cache_build_assoc 1
#define core_config_bcr_d_cache_build_capacity 5
#define core_config_bcr_d_cache_build_bsize 1
#define core_config_bcr_d_cache_build_fl 2
#define core_config_bcr_d_cache_build_ioc 0
#define core_config_bcr_d_cache_build_cp 0
#define core_config_bcr_d_cache_build_u 0
#define core_config_bcr_d_cache_build_cycles 0
#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_i_cache_build 0x00225104
#define core_config_bcr_i_cache_build_assoc 1
#define core_config_bcr_i_cache_build_version 4
#define core_config_bcr_i_cache_build_capacity 5
#define core_config_bcr_i_cache_build_bsize 2
#define core_config_bcr_i_cache_build_fl 2
#define core_config_bcr_i_cache_build_d 0
#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 0x00001520
#define core_config_bcr_xy_build_memsize 1
#define core_config_bcr_xy_build_interleaved 1
#define core_config_bcr_xy_build_config 1
#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 0
#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 0x12047402
#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 0
#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_fpu_build 0x01000f02
#define core_config_bcr_fpu_build_da 1
#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 0x00000002
#define core_config_bcr_bs_build_version 2
#define core_config_bcr_agu_build 0x01988c02
#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 2
#define core_config_bcr_stack_region_build 0x00000002
#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_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_mpu_present 1
#define core_config_mpu 1
#define core_config_mpu_regions 16
#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_code_density 1
#define core_config_div_rem "radix2"
#define core_config_div_rem_radix2 1
#define core_config_dsp_itu 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_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_y"
#define core_config_xy_config_dccm_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_y_base 0xe0000000
#define core_config_fpus_div 1
#define core_config_fpu_mac 1
#define core_config_fpus_mpy_fast 1
#define core_config_fpus_div_slow 1
#define core_config_bitstream 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_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_dcache_present 1
#define core_config_dcache_size 16384
#define core_config_dcache_line_size 32
#define core_config_dcache_ways 2
#define core_config_dcache_feature 2
#define core_config_icache_present 1
#define core_config_icache_size 16384
#define core_config_icache_line_size 32
#define core_config_icache_ways 2
#define core_config_icache_feature 2
#define core_config_dccm_present 1
#define core_config_dccm_size 0x80000
#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 0x80000
#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"
#endif /* H_CORE_CONFIG */

View File

@@ -1,73 +0,0 @@
/* ------------------------------------------
* Copyright (c) 2017, Synopsys, Inc. All rights reserved.
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
* 1) Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2) Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
* 3) Neither the name of the Synopsys, Inc., nor the names of its contributors may
* be used to endorse or promote products derived from this software without
* specific prior written permission.
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
--------------------------------------------- */
#ifndef H_NSIM
#define H_NSIM
#include "arc/arc_feature_config.h"
#include "arc/arc_em.h"
#include "arc/arc_timer.h"
#include "nsim_uart_obj.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 (1000000)
#endif
/* common macros must be defined by all boards */
#define BOARD_CONSOLE_UART_ID NSIM_UART_0_ID
#define BOARD_CONSOLE_UART_BAUD 115200
#define BOARD_SYS_TIMER_ID TIMER_0
#define BOARD_SYS_TIMER_INTNO INTNO_TIMER0
#define BOARD_SYS_TIMER_HZ (1000)
/** board timer 1ms means what HZ count */
#define BOARD_SYS_TIMER_MS_HZ (1000)
/** board ms counter convention based on the global timer counter */
#define BOARD_SYS_TIMER_MS_CONV (BOARD_SYS_TIMER_MS_HZ / BOARD_SYS_TIMER_HZ)
#define BOARD_OS_TIMER_ID TIMER_0
#define BOARD_OS_TIMER_INTNO INTNO_TIMER0
#define BOARD_CPU_CLOCK CLK_CPU
#define button_read(x) 1
#define led_write(x, y) EMBARC_PRINTF("led out: %x, %x\r\n", x, y)
#define BOARD_LED_MASK 0xff
#endif /* H_NSIM */

View File

@@ -1,58 +0,0 @@
/* ------------------------------------------
* Copyright (c) 2017, Synopsys, Inc. All rights reserved.
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
* 1) Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2) Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
* 3) Neither the name of the Synopsys, Inc., nor the names of its contributors may
* be used to endorse or promote products derived from this software without
* specific prior written permission.
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
--------------------------------------------- */
#ifndef H_NSIM_UART_OBJ
#define H_NSIM_UART_OBJ
#include "device/ip_hal/dev_uart.h"
/**
* NSIM UART Object Number
*/
#define DW_UART_NUM (1) /*!< NSIM UART valid number */
/**
* NSIM UART Object ID Macros
*/
#define NSIM_UART_0_ID (0) /*!< uart 0 id macro */
/**
* NSIM UART Object Control Macros
*/
#define USE_NSIM_UART_0 (1) /*!< enable use nsim uart 0 (stdio) */
#ifdef __cplusplus
extern "C" {
#endif
#ifdef __cplusplus
}
#endif
#endif /* H_NSIM_UART_OBJ */

View File

@@ -0,0 +1,47 @@
#ifndef _TOS_CONFIG_H_
#define _TOS_CONFIG_H_
#include "stddef.h"
#include "embARC.h"
#define TOS_CFG_TASK_PRIO_MAX 10u // 配置TencentOS tiny默认支持的最大优先级数量
#define TOS_CFG_ROUND_ROBIN_EN 1u // 配置TencentOS tiny的内核是否开启时间片轮转
#define TOS_CFG_OBJECT_VERIFY 0u // 配置TencentOS tiny是否校验指针合法
#define TOS_CFG_EVENT_EN 1u // TencentOS tiny 事件模块功能宏
#define TOS_CFG_MMHEAP_EN 1u // 配置TencentOS tiny是否开启动态内存模块
#define TOS_CFG_MMHEAP_POOL_SIZE (1024*20) // 配置TencentOS tiny动态内存池大小
#define TOS_CFG_MMHEAP_DEFAULT_POOL_SIZE (1024*20) // 配置TencentOS tiny动态内存池大小
#define TOS_CFG_MUTEX_EN 1u // 配置TencentOS tiny是否开启互斥锁模块
#define TOS_CFG_QUEUE_EN 1u // 配置TencentOS tiny是否开启队列模块
#define TOS_CFG_TIMER_EN 1u // 配置TencentOS tiny是否开启软件定时器模块
#define TOS_CFG_SEM_EN 1u // 配置TencentOS tiny是否开启信号量模块
#define TOS_CFG_MMBLK_EN 1u
#if (TOS_CFG_QUEUE_EN > 0u)
#define TOS_CFG_MSG_EN 1u
#else
#define TOS_CFG_MSG_EN 0u
#endif
#define TOS_CFG_MSG_POOL_SIZE 10u // 配置TencentOS tiny消息队列大小
#define TOS_CFG_IDLE_TASK_STK_SIZE 256u // 配置TencentOS tiny空闲任务栈大小
#define TOS_CFG_CPU_TICK_PER_SECOND 100u // 配置TencentOS tiny的tick频率
#define TOS_CFG_CPU_CLOCK BOARD_CPU_CLOCK // 配置TencentOS tiny CPU频率
#define TOS_CFG_TIMER_AS_PROC 1u // 配置是否将TIMER配置成函数模式
#endif

View File

@@ -1,252 +0,0 @@
.ifndef __core_config_s
.define __core_config_s, 1
.define core_config_cir_identity,0x00000043
.define core_config_cir_identity_chipid,0
.define core_config_cir_identity_arcnum,0
.define core_config_cir_identity_arcver,67
.define core_config_cir_identity_family,4
.define core_config_cir_identity_corever,3
.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_mpu_build,0x00010002
.define core_config_bcr_mpu_build_i,0
.define core_config_bcr_mpu_build_s,0
.define core_config_bcr_mpu_build_regions,16
.define core_config_bcr_mpu_build_version,2
.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_d_cache_build,0x00215104
.define core_config_bcr_d_cache_build_version,4
.define core_config_bcr_d_cache_build_assoc,1
.define core_config_bcr_d_cache_build_capacity,5
.define core_config_bcr_d_cache_build_bsize,1
.define core_config_bcr_d_cache_build_fl,2
.define core_config_bcr_d_cache_build_ioc,0
.define core_config_bcr_d_cache_build_cp,0
.define core_config_bcr_d_cache_build_u,0
.define core_config_bcr_d_cache_build_cycles,0
.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,11
.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_i_cache_build,0x00225104
.define core_config_bcr_i_cache_build_assoc,1
.define core_config_bcr_i_cache_build_version,4
.define core_config_bcr_i_cache_build_capacity,5
.define core_config_bcr_i_cache_build_bsize,2
.define core_config_bcr_i_cache_build_fl,2
.define core_config_bcr_i_cache_build_d,0
.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,11
.define core_config_bcr_iccm_build_version,4
.define core_config_bcr_xy_build,0x00001520
.define core_config_bcr_xy_build_memsize,1
.define core_config_bcr_xy_build_interleaved,1
.define core_config_bcr_xy_build_config,1
.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,0
.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,0x12047402
.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,0
.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_fpu_build,0x01000f02
.define core_config_bcr_fpu_build_da,1
.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_agu_build,0x01988c02
.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,2
.define core_config_bcr_stack_region_build,0x00000002
.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_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_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_code_density,1
.define core_config_div_rem,"radix2"
.define core_config_div_rem_radix2,1
.define core_config_dsp_itu,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_mpu_present,1
.define core_config_mpu,1
.define core_config_mpu_regions,16
.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_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_y"
.define core_config_xy_config_dccm_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_y_base,0xe0000000
.define core_config_fpus_div,1
.define core_config_fpu_mac,1
.define core_config_fpuda,1
.define core_config_fpus_mpy_slow,1
.define core_config_fpus_div_slow,1
.define core_config_bitstream,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_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_dcache_present,1
.define core_config_dcache_size,16384
.define core_config_dcache_line_size,32
.define core_config_dcache_ways,2
.define core_config_dcache_feature,2
.define core_config_icache_present,1
.define core_config_icache_size,16384
.define core_config_icache_line_size,32
.define core_config_icache_ways,2
.define core_config_icache_feature,2
.define core_config_dccm_present,1
.define core_config_dccm_size,0x80000
.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,0x80000
.define core_config_iccm0_size,0x80000
.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"
.endif ; __core_config_s

View File

@@ -1,22 +1,17 @@
#include "cmsis_os.h"
#define APPLICATION_TASK_STK_SIZE 1024*64
#include <stdio.h>
extern void application_entry(void *arg);
osThreadDef(application_entry, osPriorityNormal, 1, APPLICATION_TASK_STK_SIZE);
EMBARC_WEAK void application_entry(void *arg)
{
while (1) {
printf("This is a demo task,please use your task entry!\r\n");
tos_task_delay(1000);
}
}
int main(void)
{
printf("Welcome to TencentOS tiny\r\n");
osKernelInitialize(); // TOS Tiny kernel initialize
osThreadCreate(osThread(application_entry), NULL); // Create TOS Tiny task
osKernelStart(); // Start TOS Tiny
printf("hello world\r\n");
printf("***I am task\r\n");
osKernelInitialize(); //TOS Tiny kernel initialize
application_entry(NULL);
osKernelStart(); //Start TOS Tiny
while (1)
{
}
}

View File

@@ -1,41 +0,0 @@
/* ------------------------------------------
* 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.
*
--------------------------------------------- */
#include "arc/arc_timer.h"
#include "board.h"
/**
* @brief necessary board hardware initialization
* @note It is better to disable interrupts when calling this function
* remember to enable interrupt when you want to use them
*/
void board_init(void)
{
arc_timer_init();
}

View File

@@ -1,129 +0,0 @@
/* ------------------------------------------
* 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.
*
--------------------------------------------- */
#include <stdio.h>
#include "nsim.h"
/**
* NSIM UART 0 Object Instantiation
*/
#if (USE_NSIM_UART_0)
static DEV_UART nsim_uart_0; /*!< nsim uart object */
/** nsim uart 0 open */
static int32_t nsim_uart_0_open(uint32_t baud)
{
/* no need to open, stdio is used */
return 0;
}
/** nsim uart 0 close */
static int32_t nsim_uart_0_close(void)
{
return 0;
}
/** nsim uart 0 control */
static int32_t nsim_uart_0_control(uint32_t ctrl_cmd, void *param)
{
return 0;
}
/** nsim uart 0 write */
static int32_t nsim_uart_0_write(const void *data, uint32_t len)
{
return fwrite(data, len, sizeof(uint8_t), stdout);
}
/** nsim uart 0 close */
static int32_t nsim_uart_0_read(void *data, uint32_t len)
{
uint32_t i;
int32_t c;
for (i = 0; i < len; i++) {
c = getchar();
if (c < 0) {
break;
}
if (c == 10) {
c = 13;
}
*((uint8_t *)data) = (uint8_t)c;
data++;
}
return i;
}
/** install nsim uart 0 to system */
static void nsim_uart_0_install(void)
{
DEV_UART *nsim_uart_ptr = &nsim_uart_0;
/** uart dev init */
nsim_uart_ptr->uart_open = nsim_uart_0_open;
nsim_uart_ptr->uart_close = nsim_uart_0_close;
nsim_uart_ptr->uart_control = nsim_uart_0_control;
nsim_uart_ptr->uart_write = nsim_uart_0_write;
nsim_uart_ptr->uart_read = nsim_uart_0_read;
}
#endif /* USE_DW_UART_0 */
/**
* \brief install all uart objects
* \note \b MUST be called during system init
*/
static void nsim_uart_all_install(void)
{
#if (USE_NSIM_UART_0)
nsim_uart_0_install();
#endif
}
/** get one uart 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;
nsim_uart_all_install();
}
switch (uart_id) {
#if (USE_NSIM_UART_0)
case NSIM_UART_0_ID:
return &nsim_uart_0;
break;
#endif
default:
break;
}
return NULL;
}

View File

@@ -1,259 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<?fileVersion 4.0.0?><cproject storage_type_id="org.eclipse.cdt.core.XmlProjectDescriptionStorage">
<storageModule moduleId="org.eclipse.cdt.core.settings">
<cconfiguration id="org.eclipse.cdt.cross.arc.gnu.linux.elf.debug.1536038980">
<storageModule buildSystemId="org.eclipse.cdt.managedbuilder.core.configurationDataProvider" id="org.eclipse.cdt.cross.arc.gnu.linux.elf.debug.1536038980" moduleId="org.eclipse.cdt.core.settings" name="arcem">
<externalSettings/>
<extensions>
<extension id="org.eclipse.cdt.core.GNU_ELF" point="org.eclipse.cdt.core.BinaryParser"/>
<extension id="org.eclipse.cdt.core.GmakeErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
<extension id="org.eclipse.cdt.core.CWDLocator" point="org.eclipse.cdt.core.ErrorParser"/>
<extension id="org.eclipse.cdt.core.GCCErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
<extension id="org.eclipse.cdt.core.GASErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
<extension id="org.eclipse.cdt.core.GLDErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
</extensions>
</storageModule>
<storageModule moduleId="cdtBuildSystem" version="4.0.0">
<configuration artifactName="${ProjName}" buildArtefactType="org.eclipse.cdt.cross.arc.gnu.buildArtefactType.application" buildProperties="org.eclipse.cdt.build.core.buildArtefactType=org.eclipse.cdt.cross.arc.gnu.buildArtefactType.application,org.eclipse.cdt.build.core.buildType=org.eclipse.cdt.build.core.buildType.debug" description="ARC ARCEM" id="org.eclipse.cdt.cross.arc.gnu.linux.elf.debug.1536038980" name="arcem" optionalBuildProperties="" parent="org.eclipse.cdt.cross.arc.gnu.linux.elf.debug">
<folderInfo id="org.eclipse.cdt.cross.arc.gnu.linux.elf.debug.1536038980." name="/" resourcePath="">
<toolChain id="org.eclipse.cdt.cross.arc.gnu.linux.elf.toolchain.debug.1518186599" name="GNU Toolchain for ARC EM" superClass="org.eclipse.cdt.cross.arc.gnu.linux.elf.toolchain.debug">
<option id="org.eclipse.cdt.cross.arc.gnu.linux.option.debugging.level.2042344771" name="Debug level" superClass="org.eclipse.cdt.cross.arc.gnu.linux.option.debugging.level" value="org.eclipse.cdt.cross.arc.gnu.base.option.debugging.level.max" valueType="enumerated"/>
<targetPlatform id="org.eclipse.cdt.cross.arc.gnu.linux.elf.platform.debug.589546950" isAbstract="false" name="All Platform" superClass="org.eclipse.cdt.cross.arc.gnu.linux.elf.platform.debug"/>
<builder autoBuildTarget="all" buildPath="${workspace_loc:/blinky}" cleanBuildTarget="clean" enableAutoBuild="false" enableCleanBuild="true" enabledIncrementalBuild="true" id="org.eclipse.cdt.cross.arc.gnu.linux.elf.builder.debug.1840405665" incrementalBuildTarget="all" keepEnvironmentInBuildfile="false" managedBuildOn="false" name="GNU Make Builder for ARC" parallelBuildOn="false" superClass="org.eclipse.cdt.cross.arc.gnu.linux.elf.builder.debug"/>
<tool id="org.eclipse.cdt.cross.arc.gnu.linux.elf.assembler.debug.420501660" name="ARC ELF32 GCC Assembler" superClass="org.eclipse.cdt.cross.arc.gnu.linux.elf.assembler.debug">
<option IS_BUILTIN_EMPTY="false" IS_VALUE_EMPTY="false" id="org.eclipse.cdt.cross.arc.gnu.assembler.option.include.paths.1349156369" name="Include paths (-I)" superClass="org.eclipse.cdt.cross.arc.gnu.assembler.option.include.paths" valueType="includePath">
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/blinky}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/blinky/tencentos/kernel/core/include}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/blinky/tencentos/kernel/pm/include}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/blinky/tencentos/kernel/hal/include}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/blinky/tencentos/arch/arc/nsim/common/include}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/blinky/tencentos/arch/arc/nsim/em/gcc}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/blinky/tencentos/board/ARC_NSIM_EM/TOS-CONFIG}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/blinky/tencentos/osal/cmsis_os}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/blinky/tencentos/board/ARC_NSIM_EM/BSP/Inc}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/blinky/tencentos/platform/vendor_bsp/embarc_bsp/include}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/blinky/tencentos/platform/vendor_bsp/embarc_bsp/library}&quot;"/>
</option>
<option IS_BUILTIN_EMPTY="false" IS_VALUE_EMPTY="false" id="org.eclipse.cdt.cross.arc.gnu.assembler.option.preprocessor.def.311605714" name="Defined symbols (-D)" superClass="org.eclipse.cdt.cross.arc.gnu.assembler.option.preprocessor.def" valueType="definedSymbols">
<listOptionValue builtIn="false" value="BOARD_CPU_FREQ=25000000"/>
<listOptionValue builtIn="false" value="BOARD_DEV_FREQ=50000000"/>
<listOptionValue builtIn="false" value="BOARD_NSIM"/>
<listOptionValue builtIn="false" value="CPU_ARC"/>
<listOptionValue builtIn="false" value="CURRENT_CORE=arcem"/>
<listOptionValue builtIn="false" value="EMBARC_TCF_GENERATED"/>
<listOptionValue builtIn="false" value="EMBARC_USE_BOARD_MAIN"/>
<listOptionValue builtIn="false" value="HW_VERSION=10"/>
<listOptionValue builtIn="false" value="LIB_CLIB"/>
<listOptionValue builtIn="false" value="PLATFORM_EMBARC"/>
<listOptionValue builtIn="false" value="TOOLCHAIN=ARC_GNU"/>
<listOptionValue builtIn="false" value="_HAVE_LIBGLOSS_"/>
<listOptionValue builtIn="false" value="_HEAPSIZE=8192"/>
<listOptionValue builtIn="false" value="_HOSTLINK_"/>
<listOptionValue builtIn="false" value="_NSIM_"/>
<listOptionValue builtIn="false" value="_STACKSIZE=2048"/>
<listOptionValue builtIn="false" value="__GNU__"/>
</option>
<inputType id="org.eclipse.cdt.cross.arc.gnu.linux.assembler.base.input.1466071146"/>
<inputType id="org.eclipse.cdt.cross.arc.gnu.em.linux.assembler.base.input.1280163649" superClass="org.eclipse.cdt.cross.arc.gnu.em.linux.assembler.base.input"/>
</tool>
<tool id="org.eclipse.cdt.cross.arc.gnu.linux.elf.c.compiler.debug.448240261" name="ARC ELF32 GCC C Compiler" superClass="org.eclipse.cdt.cross.arc.gnu.linux.elf.c.compiler.debug">
<option IS_BUILTIN_EMPTY="false" IS_VALUE_EMPTY="false" id="org.eclipse.cdt.cross.arc.gnu.c.compiler.option.include.paths.79614265" name="Include paths (-I)" superClass="org.eclipse.cdt.cross.arc.gnu.c.compiler.option.include.paths" valueType="includePath">
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/blinky}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/blinky/tencentos/kernel/core/include}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/blinky/tencentos/kernel/pm/include}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/blinky/tencentos/kernel/hal/include}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/blinky/tencentos/arch/arc/nsim/common/include}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/blinky/tencentos/arch/arc/nsim/em/gcc}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/blinky/tencentos/board/ARC_NSIM_EM/TOS-CONFIG}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/blinky/tencentos/osal/cmsis_os}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/blinky/tencentos/board/ARC_NSIM_EM/BSP/Inc}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/blinky/tencentos/platform/vendor_bsp/embarc_bsp/include}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/blinky/tencentos/platform/vendor_bsp/embarc_bsp/library}&quot;"/>
</option>
<option IS_BUILTIN_EMPTY="false" IS_VALUE_EMPTY="false" id="org.eclipse.cdt.cross.arc.gnu.c.compiler.option.preprocessor.def.1347816001" name="Defined symbols (-D)" superClass="org.eclipse.cdt.cross.arc.gnu.c.compiler.option.preprocessor.def" valueType="definedSymbols">
<listOptionValue builtIn="false" value="BOARD_CPU_FREQ=25000000"/>
<listOptionValue builtIn="false" value="BOARD_DEV_FREQ=50000000"/>
<listOptionValue builtIn="false" value="BOARD_NSIM"/>
<listOptionValue builtIn="false" value="CPU_ARC"/>
<listOptionValue builtIn="false" value="CURRENT_CORE=arcem"/>
<listOptionValue builtIn="false" value="EMBARC_TCF_GENERATED"/>
<listOptionValue builtIn="false" value="EMBARC_USE_BOARD_MAIN"/>
<listOptionValue builtIn="false" value="HW_VERSION=10"/>
<listOptionValue builtIn="false" value="LIB_CLIB"/>
<listOptionValue builtIn="false" value="PLATFORM_EMBARC"/>
<listOptionValue builtIn="false" value="TOOLCHAIN=ARC_GNU"/>
<listOptionValue builtIn="false" value="_HAVE_LIBGLOSS_"/>
<listOptionValue builtIn="false" value="_HEAPSIZE=8192"/>
<listOptionValue builtIn="false" value="_HOSTLINK_"/>
<listOptionValue builtIn="false" value="_NSIM_"/>
<listOptionValue builtIn="false" value="_STACKSIZE=2048"/>
<listOptionValue builtIn="false" value="__GNU__"/>
</option>
<option id="org.eclipse.cdt.cross.arc.gnu.c.compiler.option.optimization.level.1856088319" name="Optimization level" superClass="org.eclipse.cdt.cross.arc.gnu.c.compiler.option.optimization.level" value="org.eclipse.cdt.cross.arc.gnu.base.option.optimization.level.none" valueType="enumerated"/>
<inputType id="org.eclipse.cdt.cross.arc.gnu.linux.c.compiler.base.input.1213319901"/>
<inputType id="org.eclipse.cdt.cross.arc.gnu.em.linux.c.compiler.base.input.119616919" superClass="org.eclipse.cdt.cross.arc.gnu.em.linux.c.compiler.base.input"/>
</tool>
<tool id="org.eclipse.cdt.cross.arc.gnu.linux.elf.cpp.compiler.debug.1443248443" name="ARC ELF32 GCC C++ Compiler" superClass="org.eclipse.cdt.cross.arc.gnu.linux.elf.cpp.compiler.debug">
<inputType id="org.eclipse.cdt.cross.arc.gnu.em.linux.cpp.compiler.base.input.664957218" superClass="org.eclipse.cdt.cross.arc.gnu.em.linux.cpp.compiler.base.input"/>
</tool>
<tool id="org.eclipse.cdt.cross.arc.gnu.linux.elf.c.linker.debug.1864971900" name="ARC ELF32 GCC C Linker" superClass="org.eclipse.cdt.cross.arc.gnu.linux.elf.c.linker.debug">
<inputType id="org.eclipse.cdt.cross.arc.gnu.c.linker.input.976252164" superClass="org.eclipse.cdt.cross.arc.gnu.c.linker.input">
<additionalInput kind="additionalinputdependency" paths="$(USER_OBJS)"/>
<additionalInput kind="additionalinput" paths="$(LIBS)"/>
</inputType>
</tool>
<tool id="org.eclipse.cdt.cross.arc.gnu.linux.elf.cpp.linker.debug.116146273" name="ARC ELF32 GCC C++ Linker" superClass="org.eclipse.cdt.cross.arc.gnu.linux.elf.cpp.linker.debug"/>
<tool id="org.eclipse.cdt.cross.arc.gnu.linux.elf.createflash.debug.2095919826" name="ARC ELF32 GNU Create Flash Image" superClass="org.eclipse.cdt.cross.arc.gnu.linux.elf.createflash.debug"/>
<tool id="org.eclipse.cdt.cross.arc.gnu.linux.elf.createlisting.debug.207593566" name="ARC ELF32 GNU Create Listing" superClass="org.eclipse.cdt.cross.arc.gnu.linux.elf.createlisting.debug"/>
<tool id="org.eclipse.cdt.cross.arc.gnu.linux.printsize.base.615400078" name="ARC ELF32 GNU Print Size" superClass="org.eclipse.cdt.cross.arc.gnu.linux.printsize.base"/>
<tool id="org.eclipse.cdt.cross.arc.gnu.em.linux.archiver.base.1467791402" name="ARC ELF32 GCC Archiver" superClass="org.eclipse.cdt.cross.arc.gnu.em.linux.archiver.base"/>
</toolChain>
</folderInfo>
</configuration>
</storageModule>
<storageModule moduleId="org.eclipse.cdt.core.externalSettings"/>
</cconfiguration>
</storageModule>
<storageModule moduleId="cdtBuildSystem" version="4.0.0">
<project id="baremetal_arc_feature_cache.org.eclipse.cdt.cross.arc.gnu.linux.elf.1234567890" name="ARC Cross ELF32 Target Application" projectType="org.eclipse.cdt.cross.arc.gnu.linux.elf"/>
</storageModule>
<storageModule moduleId="scannerConfiguration">
<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId=""/>
</storageModule>
<storageModule moduleId="org.eclipse.cdt.core.LanguageSettingsProviders"/>
<storageModule moduleId="refreshScope" versionNumber="2">
<configuration configurationName="arcem">
<resource resourceType="PROJECT" workspacePath="/blinky"/>
</configuration>
</storageModule>
<storageModule moduleId="org.eclipse.cdt.internal.ui.text.commentOwnerProjectMappings"/>
<storageModule moduleId="org.eclipse.cdt.make.core.buildtargets"/>
</cproject>

View File

@@ -1,14 +0,0 @@
### 运行IDE步骤
1. 修改文件`.project`中tencentos-tiny的路径
```
<variableList>
<variable>
<name>TencentOS_ROOT</name>
<value>file:/C:/Users/jingru/Documents/git/tencentos/TencentOS-tiny</value>
</variable>
</variableList>
```
2. 打开ide点击**File->Open Projects From File system**, 添加`hello_world`根路径。
3. 点击**Denug**启动调试

View File

@@ -1,237 +0,0 @@
##########################################################################################################################
# File automatically-generated by tool: [projectgenerator] version: [3.3.0] date: [Mon Aug 05 10:29:11 CST 2019]
##########################################################################################################################
# ------------------------------------------------
# Generic Makefile (based on gcc)
#
# ChangeLog :
# 2017-02-10 - Several enhancements + project update mode
# 2015-07-22 - first version
# ------------------------------------------------
######################################
# target
######################################
TARGET = TencentOS_tiny
######################################
# building variables
######################################
# debug build?
DEBUG = 1
# optimization
OPT = -O0
TOP_DIR = ../../../../
#######################################
# paths
#######################################
# Build path
BUILD_DIR = build
######################################
# source
######################################
# C sources
KERNEL_SRC = \
${wildcard $(TOP_DIR)/kernel/core/*.c}
C_SOURCES += $(KERNEL_SRC)
ARCH_SRC = \
${wildcard $(TOP_DIR)/arch/arc/nsim/em/gcc/*.c} \
${wildcard $(TOP_DIR)/arch/arc/nsim/common/*.c}
C_SOURCES += $(ARCH_SRC)
CMSIS_SRC = \
${wildcard $(TOP_DIR)/osal/cmsis_os/*.c}
C_SOURCES += $(CMSIS_SRC)
HAL_DRIVER_SRC = \
$(TOP_DIR)/board/ARC_NSIM_EM/BSP/Src/main.c \
$(TOP_DIR)/board/ARC_NSIM_EM/BSP/Src/nsim_init.c \
$(TOP_DIR)/board/ARC_NSIM_EM/BSP/Src/nsim_uart_obj.c \
$(TOP_DIR)/examples/hello_world/hello_world.c \
$(TOP_DIR)/platform/vendor_bsp/embarc_bsp/board/board.c \
$(TOP_DIR)/platform/vendor_bsp/embarc_bsp/arc/startup/arc_cxx_support.c \
$(TOP_DIR)/platform/vendor_bsp/embarc_bsp/arc/arc_cache.c \
$(TOP_DIR)/platform/vendor_bsp/embarc_bsp/arc/arc_connect.c \
$(TOP_DIR)/platform/vendor_bsp/embarc_bsp/arc/arc_exception.c \
$(TOP_DIR)/platform/vendor_bsp/embarc_bsp/arc/arc_mp.c \
$(TOP_DIR)/platform/vendor_bsp/embarc_bsp/arc/arc_mpu.c \
$(TOP_DIR)/platform/vendor_bsp/embarc_bsp/arc/arc_timer.c \
$(TOP_DIR)/platform/vendor_bsp/embarc_bsp/arc/arc_udma.c \
$(TOP_DIR)/platform/vendor_bsp/embarc_bsp/arc/arc_util.c \
$(TOP_DIR)/platform/vendor_bsp/embarc_bsp/library/clib/embARC_sbrk.c \
$(TOP_DIR)/platform/vendor_bsp/embarc_bsp/library/clib/embARC_syscalls.c \
$(TOP_DIR)/platform/vendor_bsp/embarc_bsp/library/console/xprintf/xprintf.c \
$(TOP_DIR)/platform/vendor_bsp/embarc_bsp/library/console/console_io.c
C_SOURCES += $(HAL_DRIVER_SRC)
# ASM sources
ASM_SOURCES = \
$(TOP_DIR)/platform/vendor_bsp/embarc_bsp/arc/startup/arc_startup.s \
$(TOP_DIR)/platform/vendor_bsp/embarc_bsp/arc/arc_exc_asm.s
ASM_SOURCES_S = \
$(TOP_DIR)/arch/arc/nsim/em/gcc/port_s.S
#######################################
# binaries
#######################################
PREFIX = arc-elf32-
# The gcc compiler bin path can be either defined in make command via GCC_PATH variable (> make GCC_PATH=xxx)
# either it can be added to the PATH environment variable.
ifdef GCC_PATH
CC = $(GCC_PATH)/$(PREFIX)gcc
AS = $(GCC_PATH)/$(PREFIX)gcc -x assembler-with-cpp
CP = $(GCC_PATH)/$(PREFIX)objcopy
SZ = $(GCC_PATH)/$(PREFIX)size
else
CC = $(PREFIX)gcc
AS = $(PREFIX)gcc -x assembler-with-cpp
CP = $(PREFIX)objcopy
SZ = $(PREFIX)size
endif
HEX = $(CP) -O ihex
BIN = $(CP) -O binary -S
#######################################
# CFLAGS
#######################################
# cpu
# CPU = -mcpu=cortex-m4
# # fpu
# FPU = -mfpu=fpv4-sp-d16
# # float-abi
# FLOAT-ABI = -mfloat-abi=hard
# # mcu
# MCU = $(CPU) -mthumb $(FPU) $(FLOAT-ABI)
# macros for gcc
# AS defines
AS_DEFS =
# C defines -DLIB_CONSOLE
C_DEFS = \
-DLIB_CONSOLE \
-DBOARD_NSIM \
-DCURRENT_CORE=arcem \
-DEMBARC_TCF_GENERATED \
-DHW_VERSION=10 \
-DLIB_CLIB \
-D_HAVE_LIBGLOSS_ \
-D_HEAPSIZE=8192 \
-D_HOSTLINK_ \
-D_NSIM_ \
-D_STACKSIZE=2048 \
-D__GNU__
# AS includes
AS_INCLUDES =
# C includes
KERNEL_INC = \
-I $(TOP_DIR)/kernel/core/include \
-I $(TOP_DIR)/kernel/pm/include \
-I $(TOP_DIR)/kernel/hal/include \
-I $(TOP_DIR)/arch/arc/nsim/common/include \
-I $(TOP_DIR)/arch/arc/nsim/em/gcc \
-I $(TOP_DIR)/board/ARC_NSIM_EM/TOS-CONFIG
C_INCLUDES += $(KERNEL_INC)
CMSIS_INC = \
-I $(TOP_DIR)/osal/cmsis_os
C_INCLUDES += $(CMSIS_INC)
HAL_DRIVER_INC = \
-I $(TOP_DIR)/board/ARC_NSIM_EM/BSP/Inc \
-I $(TOP_DIR)/platform/vendor_bsp/embarc_bsp/include \
-I $(TOP_DIR)/platform/vendor_bsp/embarc_bsp/board \
-I $(TOP_DIR)/platform/vendor_bsp/embarc_bsp/library
C_INCLUDES += $(HAL_DRIVER_INC)
# compile gcc flags
ASFLAGS = -mcpu=em4_dmips -mlittle-endian -mcode-density -mdiv-rem -mswap -mnorm -mmpy-option=6 -mbarrel-shifter --param l1-cache-size=16384 --param l1-cache-line-size=32 $(C_DEFS) $(C_INCLUDES) $(OPT) -fdata-sections -ffunction-sections -mno-sdata -g
CFLAGS = -mcpu=em4_dmips -mlittle-endian -mcode-density -mdiv-rem -mswap -mnorm -mmpy-option=6 -mbarrel-shifter --param l1-cache-size=16384 --param l1-cache-line-size=32 $(C_DEFS) $(C_INCLUDES) $(OPT) -fdata-sections -ffunction-sections -mno-sdata -g -std=gnu99
# ifeq ($(DEBUG), 1)
# CFLAGS += -g -gdwarf-2
# endif
# Generate dependency information
CFLAGS += -MMD -MP -MF"$(@:%.o=%.d)"
#######################################
# LDFLAGS
#######################################
# link script
LDSCRIPT = linker_template_gnu.ldf
# libraries -lc -lm -lnosys
LIBS = -lc -lgcc
LIBDIR =
LDFLAGS = --specs=nsim.specs -mcpu=em4_dmips -mlittle-endian -mcode-density -mdiv-rem -mswap -mnorm -mmpy-option=6 -mbarrel-shifter --param l1-cache-size=16384 --param l1-cache-line-size=32 $(LIBDIR) $(LIBS) -mno-sdata -nostartfiles -Wl,-M,-Map=$(BUILD_DIR)/$(TARGET).map -lm -Wl,--script=$(LDSCRIPT)
# default action: build all
all: $(BUILD_DIR)/$(TARGET).elf $(BUILD_DIR)/$(TARGET).hex $(BUILD_DIR)/$(TARGET).bin
#######################################
# build the application
#######################################
# list of objects
OBJECTS = $(addprefix $(BUILD_DIR)/,$(notdir $(C_SOURCES:.c=.o)))
vpath %.c $(sort $(dir $(C_SOURCES)))
# list of ASM program objects
OBJECTS += $(addprefix $(BUILD_DIR)/,$(notdir $(ASM_SOURCES:.s=.o)))
vpath %.s $(sort $(dir $(ASM_SOURCES)))
OBJECTS += $(addprefix $(BUILD_DIR)/,$(notdir $(ASM_SOURCES_S:.S=.o)))
vpath %.S $(sort $(dir $(ASM_SOURCES_S)))
$(BUILD_DIR)/%.o: %.c Makefile | $(BUILD_DIR)
$(CC) -c $(CFLAGS) $< -o $@
$(BUILD_DIR)/%.o: %.s Makefile | $(BUILD_DIR)
$(AS) -c $(CFLAGS) $< -o $@
$(BUILD_DIR)/%.o: %.S Makefile | $(BUILD_DIR)
$(AS) -c $(CFLAGS) $< -o $@
$(BUILD_DIR)/$(TARGET).elf: $(OBJECTS) Makefile
$(CC) $(OBJECTS) $(LDFLAGS) -o $@
$(SZ) $@
$(BUILD_DIR)/%.hex: $(BUILD_DIR)/%.elf | $(BUILD_DIR)
$(HEX) $< $@
$(BUILD_DIR)/%.bin: $(BUILD_DIR)/%.elf | $(BUILD_DIR)
$(BIN) $< $@
$(BUILD_DIR):
mkdir $@
#######################################
# clean up
#######################################
clean:
-rm -fR $(BUILD_DIR)
run : build/TencentOS_tiny.elf
nsimdrv -p nsim_emt=1 -propsfile nsim.props build/TencentOS_tiny.elf
#######################################
# dependencies
#######################################
-include $(wildcard $(BUILD_DIR)/*.d)
# *** EOF ***

View File

@@ -1,92 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<launchConfiguration type="com.arc.embeddedcdt.idleNative">
<stringAttribute key="com.arc.embeddedcdt.ashling_tdesc_path" value="C:\AshlingOpellaXDforARC\opella-arcem-tdesc.xml"/>
<stringAttribute key="com.arc.embeddedcdt.ashling_xml_path" value="C:\AshlingOpellaXDforARC\arc-em-cpu.xml"/>
<booleanAttribute key="com.arc.embeddedcdt.debugger_app_console" value="false"/>
<stringAttribute key="com.arc.embeddedcdt.debugger_com_ashling_port" value="COM1"/>
<stringAttribute key="com.arc.embeddedcdt.debugger_com_oepnocd_port" value="COM1"/>
<stringAttribute key="com.arc.embeddedcdt.debugger_com_port" value="COM3"/>
<stringAttribute key="com.arc.embeddedcdt.debugger_custom_gdbsever_bin_path" value=""/>
<stringAttribute key="com.arc.embeddedcdt.debugger_custom_gdbsever_command" value=""/>
<stringAttribute key="com.arc.embeddedcdt.debugger_external_ashling_default" value="true"/>
<stringAttribute key="com.arc.embeddedcdt.debugger_external_nsim_default" value="true"/>
<stringAttribute key="com.arc.embeddedcdt.debugger_external_nsimprops_default" value="false"/>
<stringAttribute key="com.arc.embeddedcdt.debugger_external_nsimtcf_default" value="false"/>
<stringAttribute key="com.arc.embeddedcdt.debugger_external_openocd_default" value="true"/>
<stringAttribute key="com.arc.embeddedcdt.debugger_external_tools" value="nSIM"/>
<stringAttribute key="com.arc.embeddedcdt.debugger_external_tools_ashling_path" value="C:\AshlingOpellaXDforARC"/>
<stringAttribute key="com.arc.embeddedcdt.debugger_external_tools_nsim_path" value="C:/ARC/nSIM/nSIM/bin/nsimdrv.exe"/>
<stringAttribute key="com.arc.embeddedcdt.debugger_external_tools_oepnocd_path" value="C:/arc_gnu/share/openocd/scripts/board/snps_em_sk.cfg"/>
<stringAttribute key="com.arc.embeddedcdt.debugger_gdb_address" value="localhost"/>
<stringAttribute key="com.arc.embeddedcdt.debugger_init_commands" value=""/>
<intAttribute key="com.arc.embeddedcdt.debugger_launch_file_format_version" value="2"/>
<stringAttribute key="com.arc.embeddedcdt.debugger_openocd_bin_path" value="C:/arc_gnu/bin/openocd.exe"/>
<booleanAttribute key="com.arc.embeddedcdt.debugger_putty_default" value="true"/>
<stringAttribute key="com.arc.embeddedcdt.debugger_run_commands" value=""/>
<booleanAttribute key="com.arc.embeddedcdt.debugger_use_nsimenableexpt" value="true"/>
<booleanAttribute key="com.arc.embeddedcdt.debugger_use_nsimhostlink" value="true"/>
<booleanAttribute key="com.arc.embeddedcdt.debugger_use_nsiminvaintruexpt" value="true"/>
<booleanAttribute key="com.arc.embeddedcdt.debugger_use_nsimjit" value="false"/>
<stringAttribute key="com.arc.embeddedcdt.debugger_use_nsimjitthread" value="1"/>
<booleanAttribute key="com.arc.embeddedcdt.debugger_use_nsimmemoexpt" value="true"/>
<booleanAttribute key="com.arc.embeddedcdt.debugger_use_nsimprops" value="false"/>
<booleanAttribute key="com.arc.embeddedcdt.debugger_use_nsimtcf" value="true"/>
<stringAttribute key="com.arc.embeddedcdt.ftdi_core" value="DEFAULT_CORE"/>
<stringAttribute key="com.arc.embeddedcdt.ftdi_device" value="CUSTOM"/>
<booleanAttribute key="com.arc.embeddedcdt.load_elf" value="true"/>
<stringAttribute key="com.arc.embeddedcdt.nsim_prop_file" value=""/>
<stringAttribute key="com.arc.embeddedcdt.nsim_tcf_file" value="C:/Users/jingru/Documents/git/gitlab/embarc/embarc_osp/board/nsim/configs/10/tcf/arcem.tcf"/>
<booleanAttribute key="com.arc.embeddedcdt.nsim_use_default_working_dir" value="true"/>
<stringAttribute key="com.arc.embeddedcdt.nsim_working_directory" value="${workspace_loc:blinky}"/>
<stringAttribute key="com.arc.embeddedcdt.timestamp" value="1584601942256"/>
<booleanAttribute key="org.eclipse.cdt.debug.mi.core.AUTO_SOLIB" value="true"/>
<listAttribute key="org.eclipse.cdt.debug.mi.core.AUTO_SOLIB_LIST"/>
<stringAttribute key="org.eclipse.cdt.debug.mi.core.DEBUG_NAME" value="arc-elf32-gdb"/>
<stringAttribute key="org.eclipse.cdt.debug.mi.core.GDB_INIT" value=".gdbinit"/>
<listAttribute key="org.eclipse.cdt.debug.mi.core.SOLIB_PATH"/>
<booleanAttribute key="org.eclipse.cdt.debug.mi.core.STOP_ON_SOLIB_EVENTS" value="false"/>
<booleanAttribute key="org.eclipse.cdt.debug.mi.core.breakpointsFullPath" value="false"/>
<stringAttribute key="org.eclipse.cdt.debug.mi.core.commandFactory" value="org.eclipse.cdt.debug.mi.core.standardCommandFactory"/>
<stringAttribute key="org.eclipse.cdt.debug.mi.core.protocol" value="mi"/>
<booleanAttribute key="org.eclipse.cdt.debug.mi.core.verboseMode" value="false"/>
<booleanAttribute key="org.eclipse.cdt.dsf.gdb.AUTO_SOLIB" value="true"/>
<listAttribute key="org.eclipse.cdt.dsf.gdb.AUTO_SOLIB_LIST"/>
<stringAttribute key="org.eclipse.cdt.dsf.gdb.DEBUG_NAME" value="arc-elf32-gdb"/>
<booleanAttribute key="org.eclipse.cdt.dsf.gdb.DEBUG_ON_FORK" value="false"/>
<booleanAttribute key="org.eclipse.cdt.dsf.gdb.EXTERNAL_CONSOLE" value="false"/>
<stringAttribute key="org.eclipse.cdt.dsf.gdb.GDB_INIT" value=".gdbinit"/>
<booleanAttribute key="org.eclipse.cdt.dsf.gdb.NON_STOP" value="false"/>
<booleanAttribute key="org.eclipse.cdt.dsf.gdb.REVERSE" value="false"/>
<stringAttribute key="org.eclipse.cdt.dsf.gdb.REVERSE_MODE" value="UseSoftTrace"/>
<listAttribute key="org.eclipse.cdt.dsf.gdb.SOLIB_PATH"/>
<stringAttribute key="org.eclipse.cdt.dsf.gdb.TRACEPOINT_MODE" value="TP_NORMAL_ONLY"/>
<booleanAttribute key="org.eclipse.cdt.dsf.gdb.UPDATE_THREADLIST_ON_SUSPEND" value="false"/>
<intAttribute key="org.eclipse.cdt.launch.ATTR_BUILD_BEFORE_LAUNCH_ATTR" value="2"/>
<stringAttribute key="org.eclipse.cdt.launch.DEBUGGER_ID" value="com.arc.embeddedcdt.RemoteGDBDebugger"/>
<stringAttribute key="org.eclipse.cdt.launch.DEBUGGER_REGISTER_GROUPS" value=""/>
<stringAttribute key="org.eclipse.cdt.launch.DEBUGGER_START_MODE" value="run"/>
<booleanAttribute key="org.eclipse.cdt.launch.DEBUGGER_STOP_AT_MAIN" value="true"/>
<stringAttribute key="org.eclipse.cdt.launch.DEBUGGER_STOP_AT_MAIN_SYMBOL" value="board_main"/>
<booleanAttribute key="org.eclipse.cdt.launch.ENABLE_REGISTER_BOOKKEEPING" value="false"/>
<booleanAttribute key="org.eclipse.cdt.launch.ENABLE_VARIABLE_BOOKKEEPING" value="false"/>
<stringAttribute key="org.eclipse.cdt.launch.FORMAT" value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&lt;contentList/&gt;"/>
<stringAttribute key="org.eclipse.cdt.launch.GLOBAL_VARIABLES" value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;globalVariableList/&gt;&#13;&#10;"/>
<stringAttribute key="org.eclipse.cdt.launch.MEMORY_BLOCKS" value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;memoryBlockExpressionList/&gt;&#13;&#10;"/>
<stringAttribute key="org.eclipse.cdt.launch.PROGRAM_NAME" value="./build/TencentOS_tiny.elf"/>
<stringAttribute key="org.eclipse.cdt.launch.PROJECT_ATTR" value="blinky"/>
<booleanAttribute key="org.eclipse.cdt.launch.PROJECT_BUILD_CONFIG_AUTO_ATTR" value="false"/>
<stringAttribute key="org.eclipse.cdt.launch.PROJECT_BUILD_CONFIG_ID_ATTR" value=""/>
<stringAttribute key="org.eclipse.debug.core.ATTR_GDBSERVER_COMMAND" value="gdbserver"/>
<stringAttribute key="org.eclipse.debug.core.ATTR_GDBSERVER_PORT" value="49105"/>
<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_PATHS">
<listEntry value="/blinky"/>
</listAttribute>
<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_TYPES">
<listEntry value="4"/>
</listAttribute>
<listAttribute key="org.eclipse.debug.ui.favoriteGroups">
<listEntry value="org.eclipse.debug.ui.launchGroup.debug"/>
</listAttribute>
<stringAttribute key="org.eclipse.dsf.launch.MEMORY_BLOCKS" value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;memoryBlockExpressionList context=&quot;reserved-for-future-use&quot;/&gt;&#13;&#10;"/>
<stringAttribute key="process_factory_id" value="org.eclipse.cdt.dsf.gdb.GdbProcessFactory"/>
</launchConfiguration>

View File

@@ -1,104 +0,0 @@
MEMORY
{
REGION_ICCM : ORIGIN = 0x00000000, LENGTH = 0x80000
REGION_DCCM : ORIGIN = 0x80000000, LENGTH = 0x80000
REGION_YCCM : ORIGIN = 0xe0000000, LENGTH = 8192
}
ENTRY(_start)
SECTIONS
{
.init :
{
. = . + 0x0;
_f_init = .;
KEEP (*(.init_vector .init_vector.*))
KEEP (*(.init_bootstrap .init_bootstrap.*))
_e_init = .;
} > REGION_ICCM
.vector : ALIGN(1024)
{
_f_vector = .;
*(.vector .vector.*)
_e_vector = .;
} > REGION_ICCM
.y_ccm (NOLOAD) : ALIGN(8)
{
_f_y_ccm = .;
*(.y_ccm .y_ccm.*)
_e_y_ccm = .;
} > REGION_YCCM
.text : ALIGN(4)
{
_f_text = .;
*(.text .text.* .gnu.linkonce.t.*)
_e_text = .;
} > REGION_ICCM
.rodata : ALIGN(4)
{
_f_rodata = .;
. = ALIGN(4);
__CTOR_LIST__ = .;
LONG((__CTOR_END__ - __CTOR_LIST__) / 4 - 2)
KEEP(*(SORT_BY_NAME(".ctors*")))
LONG(0)
__CTOR_END__ = .;
. = ALIGN(4);
__init_array_start = .;
KEEP(*(SORT_BY_NAME(".init_array*")))
__init_array_end = .;
. = ALIGN(4);
__DTOR_LIST__ = .;
LONG((__DTOR_END__ - __DTOR_LIST__) / 4 - 2)
KEEP(*(SORT_BY_NAME(".dtors*")))
LONG(0)
__DTOR_END__ = .;
*(.rodata .rodata.* .gnu.linkonce.r.*)
_e_rodata = .;
} > REGION_ICCM
.data : ALIGN(4)
{
_f_data = .;
*(.data .data.* .gnu.linkonce.d.*)
_f_sdata = .;
__SDATA_BEGIN__ = .;
*(.sdata .sdata.* .gnu.linkonce.s.*)
PROVIDE (__sbss_start = .);
PROVIDE (___sbss_start = .);
_f_sbss = .;
*(.dynsbss)
*(.sbss .sbss.* .gnu.linkonce.sb.*)
*(.scommon)
_e_sbss = .;
PROVIDE (__sbss_end = .);
PROVIDE (___sbss_end = .);
_e_sdata = .;
_e_data = .;
} > REGION_DCCM AT > REGION_ICCM
.bss (NOLOAD) : ALIGN(8)
{
_f_bss = .;
*(.dynbss)
*(.bss .bss.* .gnu.linkonce.b.*)
*(COMMON)
_e_bss = .;
} > REGION_DCCM
.stack (NOLOAD) :
{
. = ALIGN(4);
_f_stack = .;
. = . + 2048;
_e_stack = .;
} > REGION_DCCM
.heap (NOLOAD) :
{
. = ALIGN(4);
__start_heap = . ;
_f_heap = .;
. = . + 8192;
_e_heap = .;
__end_heap = . ;
} > REGION_DCCM
_load_addr_text = LOADADDR(.text);
_load_addr_rodata = LOADADDR(.rodata);
_load_addr_data = LOADADDR(.data);
}

View File

@@ -1,68 +0,0 @@
nsim_isa_family=av2em
nsim_isa_core=3
arcver=0x3
nsim_isa_rgf_num_banks=2
nsim_isa_rgf_banked_regs=32
nsim_isa_rgf_num_regs=32
nsim_isa_rgf_num_wr_ports=2
nsim_isa_big_endian=0
nsim_isa_lpc_size=32
nsim_isa_pc_size=32
nsim_isa_addr_size=32
nsim_isa_code_density_option=2
nsim_isa_div_rem_option=1
nsim_isa_turbo_boost=1
nsim_isa_swap_option=1
nsim_isa_bitscan_option=1
nsim_isa_mpy_option=8
nsim_isa_shift_option=3
mpu_regions=16
mpu_version=2
nsim_isa_dsp_option=2
nsim_isa_dsp_complex_option=1
nsim_isa_dsp_divsqrt_option=1
nsim_isa_dsp_itu_option=1
nsim_isa_dsp_itu_option=1
nsim_isa_dsp_accshift_option=2
nsim_isa_agu_size=large
nsim_isa_agu_wb_depth=4
nsim_isa_agu_accord=1
nsim_isa_xy=1
nsim_isa_xy_config=dccm_y
nsim_isa_xy_size=8K
nsim_isa_xy_interleave=1
nsim_isa_xy_y_base=0xe0000000
nsim_isa_fpus_div_option=1
nsim_isa_fpu_mac_option=1
nsim_isa_fpuda_option=1
nsim_isa_fpu_fast_mpy_option=0
nsim_isa_fpu_fast_div_option=0
nsim_isa_bitstream_option=1
nsim_isa_enable_timer_0=1
nsim_isa_timer_0_int_level=1
nsim_isa_enable_timer_1=1
nsim_isa_timer_1_int_level=0
nsim_isa_num_actionpoints=2
nsim_isa_stack_checking=1
nsim_isa_has_dmp_peripheral=1
nsim_isa_smart_stack_entries=8
nsim_isa_number_of_interrupts=20
nsim_isa_number_of_levels=4
nsim_isa_number_of_external_interrupts=16
nsim_isa_fast_irq=1
nsim_isa_intvbase_preset=0x0
dcache=16384,32,2,a
nsim_isa_dc_feature_level=2
icache=16384,32,2,a
nsim_isa_ic_feature_level=2
dccm_size=0x80000
dccm_base=0x80000000
nsim_isa_dccm_interleave=1
iccm0_size=0x80000
iccm0_base=0x00000000
nsim_isa_pct_counters=8
nsim_isa_dmac_option=1
nsim_isa_dmac_channels=2
nsim_isa_dmac_registers=0
nsim_isa_dmac_fifo_depth=2
nsim_isa_dmac_int_config=single_internal

View File

@@ -1,55 +0,0 @@
#ifndef _TOS_CONFIG_H_
#define _TOS_CONFIG_H_
#include "nsim.h"
#define TOS_CFG_TASK_PRIO_MAX 10u
#define TOS_CFG_ROUND_ROBIN_EN 0u
#define TOS_CFG_OBJECT_VERIFY_EN 1u
#define TOS_CFG_TASK_DYNAMIC_CREATE_EN 1u
#define TOS_CFG_EVENT_EN 1u
#define TOS_CFG_MMBLK_EN 1u
#define TOS_CFG_MMHEAP_EN 1u
#define TOS_CFG_MMHEAP_DEFAULT_POOL_EN 1u
#define TOS_CFG_MMHEAP_DEFAULT_POOL_SIZE 0x8000
#define TOS_CFG_MUTEX_EN 1u
#define TOS_CFG_MESSAGE_QUEUE_EN 1u
#define TOS_CFG_MAIL_QUEUE_EN 1u
#define TOS_CFG_PRIORITY_MESSAGE_QUEUE_EN 1u
#define TOS_CFG_PRIORITY_MAIL_QUEUE_EN 1u
#define TOS_CFG_TIMER_EN 1u
#define TOS_CFG_PWR_MGR_EN 0u
#define TOS_CFG_TICKLESS_EN 0u
#define TOS_CFG_SEM_EN 1u
#define TOS_CFG_TASK_STACK_DRAUGHT_DEPTH_DETACT_EN 1u
#define TOS_CFG_FAULT_BACKTRACE_EN 0u
#define TOS_CFG_IDLE_TASK_STK_SIZE 128u
#define TOS_CFG_CPU_TICK_PER_SECOND 1000u
#define TOS_CFG_CPU_CLOCK (CLK_CPU)
#define TOS_CFG_TIMER_AS_PROC 1u
#endif

View File

@@ -0,0 +1,53 @@
<?xml version="1.0" encoding="UTF-8"?>
<windowLayout version="3" model="sash">
<mdiFrame model="sash" x="297" y="114" width="1200" height="800">
<splitPane orientation="horizontal" divider="510">
<splitPane orientation="vertical" divider="409">
<pane>
<tabbedPanel name="locals" selected="1">
<toolBar id="0" visible="0"/>
<toolBar id="1" visible="1"/>
<toolBar id="2" visible="0"/>
</tabbedPanel>
</pane>
<pane>
<tabbedPanel name="stack">
<toolBar id="0" visible="0"/>
<toolBar id="1" visible="1"/>
<toolBar id="2" visible="0"/>
</tabbedPanel>
<tabbedPanel name="globals" selected="1">
<toolBar id="0" visible="0"/>
<toolBar id="1" visible="1"/>
<toolBar id="2" visible="0"/>
<valueUpdate name="regex_name" value="k_next_task"/>
</tabbedPanel>
</pane>
</splitPane>
<splitPane orientation="vertical" divider="478">
<pane>
<tabbedPanel name="source" selected="1">
<toolBar id="0" visible="0"/>
<toolBar id="1" visible="1"/>
<toolBar id="2" visible="0"/>
<toolBar id="3" visible="0"/>
</tabbedPanel>
</pane>
<pane>
<tabbedPanel name="break">
<toolBar id="0" visible="0"/>
<toolBar id="1" visible="1"/>
<toolBar id="2" visible="0"/>
</tabbedPanel>
<tabbedPanel name="watchdisp">
<toolBar id="0" visible="0"/>
<toolBar id="1" visible="1"/>
<toolBar id="2" visible="0"/>
</tabbedPanel>
<tabbedPanel name="command" selected="1"/>
</pane>
</splitPane>
</splitPane>
</mdiFrame>
</windowLayout>

View File

@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<Config>
<CurrentWindowLayoutFile>C:\Users\zhiwei\Desktop\embARC_Workspace\TencentOS\TencentOS-tiny\board\ARC_NSIM_EM\hello_world\.sc.project\.sc.project.windows</CurrentWindowLayoutFile>
</Config>

View File

@@ -0,0 +1,90 @@
A6_mpu=1
AC600_dcache=1
AC600_icache=1
AC_dcache=1
AC_dcache_line_size=32
AC_dcache_repalg=Random
AC_dcache_size=16384
AC_dcache_ways=2
AC_icache=1
AC_icache_line_size=32
AC_icache_repalg=Random
AC_icache_size=16384
AC_icache_ways=2
ACa7_dcache=1
ACa7_icache=1
ARC5_Core_Version=3
ARC6_Core_Version=3
ARC7_Core_Version=3
ARC_DSP_memory=ARC_xy
ARC_agu=large
ARC_agu_accord=1
ARC_agu_write=4
ARC_barrel_shifter=1
ARC_bitscan=1
ARC_code_density=1
ARC_dcache_feature=2
ARC_dccm_interleave=1
ARC_default_ext_interrupts=0
ARC_default_interrupts=0
ARC_div_rem=radix2
ARC_dma=1
ARC_dmac_channels=2
ARC_dmac_fifo_depth=2
ARC_dmac_int_config=single_internal
ARC_dmac_registers=0
ARC_dsp2=1
ARC_dsp_accshift=full
ARC_dsp_complex=1
ARC_dsp_divsqrt=radix2
ARC_dsp_itu=1
ARC_ext_interrupt_num=16
ARC_fast_interrupt=1
ARC_fsfpus_div=Slow
ARC_fsfpus_mpy=Slow
ARC_icache_feature=2
ARC_interrupt_baseaddr=0x0
ARC_interrupt_num=20
ARC_interrupt_priorities=4
ARC_interrupt_vector_count=20
ARC_mpu_region=16
ARC_mpu_version=-mpu
ARC_mpy_emoption=mpyd
ARC_mpy_hsoption=mpyd
ARC_parallel_port_address=0x378
ARC_pct_counters=8
ARC_reset_on_restart=1
ARC_rgf_num_wr_ports=2
ARC_shift_assist=1
ARC_smart_stack_entries=8
ARC_swap=1
ARC_target=ARCSIM
ARC_timer0=1
ARC_timer0_level=1
ARC_timer1=1
ARC_timer1_level=0
ARC_turbo_boost=1
ARC_xy_config=dccm_y
ARC_xy_interleave=1
ARC_xy_size=8K
ARC_xy_ybase=0xe0000000
Execute_to_main=0
Local_symbols=1
Program_toggles_off=binary_stdin,binary_stdout,flush_pipe,cr_for_more
Program_toggles_on=load_at_paddr
cmd_line_option=-OKN -action_points\=2 -dmp_peripheral -OKN -action_points\=2 -dmp_peripheral -OKN -action_points\=2 -dmp_peripheral
dccm_base=0x80000000
dccm_size=0x80000
fpu_mac=1
fpuda=1
fpus_div=1
hw_stack_checking=1
iccm0_base=0x00000000
iccm0_size=0x80000
iss_av2_override=0
program=build/TencentOS_tiny.elf
v2em_core_register_per_bank=32
v2em_core_version=3
v2em_regis_bank=2
v2hs_core_version=3
which_arc=ARCV2EM

View File

@@ -0,0 +1,269 @@
##########################################################################################################################
# File automatically-generated by tool: [projectgenerator] version: [3.3.0] date: [Mon Aug 05 10:29:11 CST 2019]
##########################################################################################################################
# ------------------------------------------------
# Generic Makefile (based on gcc)
#
# ChangeLog :
# 2017-02-10 - Several enhancements + project update mode
# 2015-07-22 - first version
# ------------------------------------------------
######################################
# target
######################################
TARGET = TencentOS_tiny
APPLICATION = hello_world
######################################
# building variables
######################################
# debug build?
DEBUG = 1
# optimization
OPT = -O0
TOP_DIR = ../../..
#######################################
# paths
#######################################
# Build path
BUILD_DIR = build
#######################################
# embarc_bsp relative conifg
#######################################
BOARD ?= nsim
BD_VER ?= 10
CUR_CORE ?= arcem
TOOLCHAIN ?= mw
OLEVEL ?= O0
OUT_DIR_ROOT ?= $(BUILD_DIR)
export BOARD
export BD_VER
export CUR_CORE
export TOOLCHAIN
export OUT_DIR_ROOT
export OLEVEL
EMBARC_BSP_ROOT = $(TOP_DIR)/platform/vendor_bsp/Synopsys/ARC/embarc_bsp
EMBARC_BSP_TEST_FILE = $(EMBARC_BSP_ROOT)/arc/startup/arc_startup.s
ifeq ($(wildcard $(EMBARC_BSP_TEST_FILE)),)
$(info )
$(info )
$(info )
$(info ######################################################################################################)
$(info # #)
$(info # embarc_bsp not exist!!! #)
$(info # please git embarc_bsp from github #)
$(info # run cmd blew in folder <TOP_DIR>/platform/vendor_bsp/Synopsys/ARC>: #)
$(info # git clone https://github.com/foss-for-synopsys-dwc-arc-processors/embarc_bsp.git -b upstream #)
$(info # #)
$(info ######################################################################################################)
$(info )
$(info )
$(info )
$(error [Makefile.error]: embarc_bsp not exist!!!)
endif
EMBARC_ROOT = $(EMBARC_BSP_ROOT)
export EMBARC_ROOT
EMBARC_OUT_DIR = $(OUT_DIR_ROOT)/obj_$(BOARD)_$(BD_VER)/$(TOOLCHAIN)_$(CUR_CORE)
ifeq ($(TOOLCHAIN),mw)
COMPILER_ARG_FILE := $(EMBARC_OUT_DIR)/embARC_generated/ccac.arg
LDF_FILE := $(EMBARC_OUT_DIR)/linker_mw.ldf
MDB_ARG_FILE := $(EMBARC_OUT_DIR)/embARC_generated/mdb.arg
else
COMPILER_ARG_FILE := $(EMBARC_OUT_DIR)/embARC_generated/gcc.arg
LDF_FILE := $(EMBARC_OUT_DIR)/linker_gnu.ldf
endif
######################################
# source
######################################
# C sources
KERNEL_SRC = \
${wildcard $(TOP_DIR)/kernel/core/*.c}
C_SOURCES += $(KERNEL_SRC)
ARCH_SRC = \
${wildcard $(TOP_DIR)/arch/arc/arcem/*.c} \
${wildcard $(TOP_DIR)/arch/arc/common/*.c}
C_SOURCES += $(ARCH_SRC)
CMSIS_SRC = \
${wildcard $(TOP_DIR)/osal/cmsis_os/*.c}
C_SOURCES += $(CMSIS_SRC)
APPLICATION_SRC = \
${wildcard $(TOP_DIR)/board/ARC_NSIM_EM/BSP/Src/*.c} \
${wildcard $(TOP_DIR)/examples/$(APPLICATION)/*.c}
C_SOURCES += $(APPLICATION_SRC)
# ASM sources
ASM_SOURCES = \
$(TOP_DIR)/arch/arc/arcem/port_s.s
ifeq ($(TOOLCHAIN),mw)
PREFIX =
CC = $(PREFIX)ccac
AS = $(PREFIX)ccac
SZ = $(PREFIX)size
OBJCOPY = $(PREFIX)elf2bin
ELF2HEX = $(PREFIX)elf2hex
ELF2HEX_INOPT = -Q -I
ELF2HEX_OUTOPT = -o
ELF2BIN_OPT =
else
endif
#######################################
# CFLAGS
#######################################
# C defines
NSIM_STACK_CHECK := -DARC_FEATURE_STACK_CHECK=0
# 1: enable hardware stack check, 0 disable hardware stack check
ifeq ($(TOOLCHAIN),mw)
TOOLCHAIN_DEF := -D__MW__
else
TOOLCHAIN_DEF := -D__GNU__ -D_HAVE_LIBGLOSS_
endif
C_DEFS = \
$(TOOLCHAIN_DEF) \
$(NSIM_STACK_CHECK) \
-DBOARD_NSIM \
-DCURRENT_CORE=$(CUR_CORE) \
-DEMBARC_TCF_GENERATED \
-DHW_VERSION=$(BD_VER) \
-DLIB_CONSOLE \
-DLIB_CLIB \
-D_HEAPSIZE=8192 \
-D_HOSTLINK_ \
-D_NSIM_ \
-D_STACKSIZE=2048 \
-DARC_FEATURE_STACK_CHECK=0
# include dirs
ARCH_INC = \
-I $(TOP_DIR)/arch/arc/arcem \
-I $(TOP_DIR)/arch/arc/common/include
C_INCLUDES += $(ARCH_INC)
BOARD_INC = \
-I $(TOP_DIR)/board/ARC_NSIM_EM/BSP/Inc
C_INCLUDES += $(BOARD_INC)
KERNEL_INC = \
-I $(TOP_DIR)/kernel/core/include \
-I $(TOP_DIR)/kernel/pm/include \
-I $(TOP_DIR)/kernel/hal/include
C_INCLUDES += $(KERNEL_INC)
CMSIS_INC = \
-I $(TOP_DIR)/osal/cmsis_os
C_INCLUDES += $(CMSIS_INC)
EMBARC_BSP_INC = \
-I $(EMBARC_BSP_ROOT)/board \
-I $(EMBARC_BSP_ROOT)/board/nsim/configs/10 \
-I $(EMBARC_BSP_ROOT)/include \
-I $(EMBARC_BSP_ROOT)/include/arc \
-I $(EMBARC_BSP_ROOT)/include/device/designware \
-I $(EMBARC_BSP_ROOT)/include/device/subsystem \
-I $(EMBARC_BSP_ROOT)/library \
-I $(EMBARC_OUT_DIR)/embARC_generated
C_INCLUDES += $(EMBARC_BSP_INC)
ifeq ($(TOOLCHAIN),mw)
ASFLAGS = @$(COMPILER_ARG_FILE) -Hnoccm -Hnosdata -Wincompatible-pointer-types -Hnocopyr -Hasmcpp -$(OLEVEL) -g $(C_DEFS) $(C_INCLUDES) -MMD -MT $@ -MF $@.d
CFLAGS = @$(COMPILER_ARG_FILE) -Hnoccm -Hnosdata -Wincompatible-pointer-types -Hnocopyr -Hnocplus -$(OLEVEL) -g $(C_DEFS) $(C_INCLUDES) -MMD -MT $@ -MF $@.d
LDFLAGS = -Hhostlink @$(COMPILER_ARG_FILE) -Hnocopyr -Hnosdata -Hnocrt -Hldopt=-Coutput=$(BUILD_DIR)/mw_arcem.map -Hldopt=-Csections -Hldopt=-Ccrossfunc -Hldopt=-Csize -zstdout $(LDF_FILE)
else
endif
# default action: build all
all: $(BUILD_DIR)/$(TARGET).elf $(BUILD_DIR)/$(TARGET).hex $(BUILD_DIR)/$(TARGET).bin
#######################################
# build the application
#######################################
# list of objects
OBJECTS = $(addprefix $(BUILD_DIR)/,$(notdir $(C_SOURCES:.c=.o)))
vpath %.c $(sort $(dir $(C_SOURCES)))
# list of ASM program objects
OBJECTS += $(addprefix $(BUILD_DIR)/,$(notdir $(ASM_SOURCES:.s=.o)))
vpath %.s $(sort $(dir $(ASM_SOURCES)))
OBJECTS += $(addprefix $(BUILD_DIR)/,$(notdir $(ASM_SOURCES_S:.S=.o)))
vpath %.S $(sort $(dir $(ASM_SOURCES_S)))
# EMBARC_PREBUILT_LIBRARY = -Hldopt=-Bgrouplib
EMBARC_PREBUILT_LIBRARY = $(EMBARC_OUT_DIR)/libembarc.a
# EMBARC_PREBUILT_LIBRARY += $(EMBARC_OUT_DIR)/board/board.o
# EMBARC_PREBUILT_LIBRARY += $(EMBARC_OUT_DIR)/arc/startup/arc_startup.o
# EMBARC_PREBUILT_LIBRARY += $(EMBARC_OUT_DIR)/arc/startup/arc_cxx_support.o
# EMBARC_PREBUILT_LIBRARY += $(EMBARC_OUT_DIR)/libboard_nsim.a
# EMBARC_PREBUILT_LIBRARY += $(EMBARC_OUT_DIR)/libcpuarc.a
# EMBARC_PREBUILT_LIBRARY += $(EMBARC_OUT_DIR)/libembarc_libc.a
# EMBARC_PREBUILT_LIBRARY += $(EMBARC_OUT_DIR)/libembarc_console.a
build_embarc_lib: | $(BUILD_DIR)
make -f $(EMBARC_BSP_ROOT)/options/options.mk V=1 embarc_lib
$(BUILD_DIR)/%.o: %.c Makefile | $(BUILD_DIR)
$(CC) -c $(CFLAGS) $< -o $@
$(BUILD_DIR)/%.o: %.s Makefile | $(BUILD_DIR)
$(AS) -c $(ASFLAGS) $< -o $@
$(BUILD_DIR)/%.o: %.S Makefile | $(BUILD_DIR)
$(AS) -c $(ASFLAGS) $< -o $@
$(BUILD_DIR)/$(TARGET).elf: build_embarc_lib $(OBJECTS) Makefile
$(CC) $(LDFLAGS) $(OBJECTS) $(EMBARC_PREBUILT_LIBRARY) -o $@
$(SZ) $@
$(BUILD_DIR)/%.hex: $(BUILD_DIR)/%.elf | $(BUILD_DIR)
$(ELF2HEX) $(ELF2HEX_INOPT) $< $(ELF2HEX_OUTOPT) $@
$(BUILD_DIR)/%.bin: $(BUILD_DIR)/%.elf | $(BUILD_DIR)
$(OBJCOPY) $(ELF2BIN_OPT) $< $@
$(BUILD_DIR):
mkdir $@
#######################################
# clean up
#######################################
clean:
-rm -fR $(BUILD_DIR)
nsim_debug : $(BUILD_DIR)/$(TARGET).elf
mdb -nooptions -nogoifmain -toggle=include_local_symbols=1 -nsim -off=binary_stdin -off=binary_stdout -on=load_at_paddr -on=reset_upon_restart -off=flush_pipe -off=cr_for_more -OKN @$(MDB_ARG_FILE) $<
#######################################
# dependencies
#######################################
-include $(wildcard $(BUILD_DIR)/*.d)
# *** EOF ***

Binary file not shown.

View File

@@ -1,10 +1,10 @@
#include "cmsis_os.h"
#define TASK1_STK_SIZE 512
#define TASK1_STK_SIZE 1024
void task1(void *arg);
osThreadDef(task1, osPriorityNormal, 1, TASK1_STK_SIZE);
#define TASK2_STK_SIZE 512
#define TASK2_STK_SIZE 1024
void task2(void *arg);
osThreadDef(task2, osPriorityNormal, 1, TASK2_STK_SIZE);

Submodule platform/vendor_bsp/Synopsys/ARC/embarc_bsp added at 7595aae3c2

View File

@@ -1,403 +0,0 @@
/* ------------------------------------------
* 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.
*
--------------------------------------------- */
/**
* @file
* @ingroup ARC_HAL_MISC_CACHE
* @brief Cache manipulation
*
* This module contains functions for manipulation caches.
*/
#include "arc/arc_cache.h"
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 instruction cache lines
*
* @param start_addr Start address in instruction cache
* @param size Bytes to be invalidated
* @return 0, succeeded, -1, failed
*/
int32_t icache_invalidate_mlines(uint32_t start_addr, uint32_t size)
{
uint32_t end_addr;
uint32_t line_size;
uint32_t status;
if ((size == 0) || (size > icache_config.capacity)) {
return -1;
}
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);
arc_nop();
arc_nop();
arc_nop();
start_addr += line_size;
} while (start_addr <= end_addr);
cpu_unlock_restore(status);
return 0;
}
/**
* @brief Lock instruction cache lines
*
* @param start_addr Start address in instruction cache
* @param size 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)
{
uint32_t end_addr;
uint32_t line_size;
uint32_t status;
int32_t ercd = 0;
if ((size == 0) || (size > icache_config.capacity)) {
return -1;
}
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;
}
#if ARC_FEATURE_ICACHE_FEATURE == 2
/**
* @brief Directly write icache internal ram
*
* @param cache_addr Icache internal address(way+index+offset)
* @param tag Cache tag to write (tag+lock bit+valid bit)
* @param 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 (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 cache_addr Icache internal address(way+index+offset)
* @param tag Cache tag to read (tag+index+lock bit+valid bit)
* @param 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 (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 mem_addr Memory address
* @param tag Cache tag to read
* @param 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 (!(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;
}
#endif
/**
* @brief Invalidate data cache lines
*
* @param start_addr Start address in data cache
* @param size Bytes to be invalidated
* @return 0, succeeded, -1, failed
*/
int32_t dcache_invalidate_mlines(uint32_t start_addr, uint32_t size)
{
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);
arc_nop();
arc_nop();
arc_nop();
/* 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 data cache lines to memory
*
* @param start_addr Start address
* @param size Bytes to be flushed
* @return 0, succeeded, -1, failed
*/
int32_t dcache_flush_mlines(uint32_t start_addr, uint32_t size)
{
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_FLDL, start_addr);
arc_nop();
arc_nop();
arc_nop();
/* 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 data cache lines
*
* @param start_addr Start address in data cache
* @param size Bytes to be locked
* @return 0, succeeded, -1, failed
*/
int32_t dcache_lock_mlines(uint32_t start_addr, uint32_t size)
{
uint32_t end_addr;
uint32_t line_size;
uint32_t status;
int32_t ercd = 0;
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_LDL, start_addr);
arc_nop();
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 cache_addr Dcache internal address(way+index+offset)
* @param tag Cache tag to write
* @param 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 (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 cache_addr Dcache internal address(way+index+offset)
* @param tag Cache tag to read
* @param 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 (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 mem_addr Memory address(tag+index+offset)
* @param tag Cache tag to read
* @param 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 (!(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();
}
}

View File

@@ -1,964 +0,0 @@
/* ------------------------------------------
* 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.
*
--------------------------------------------- */
/**
* @file
* @ingroup ARC_HAL_MISC_CONNECT
* @brief ar connect driver
*
* This module contains functions for arc connect module.
*/
#include "arc/arc_connect.h"
#include "arc/arc_mp.h"
static ARC_SPINLOCK_T arc_connect_lock;
/**
* @brief Execute arc connect command
*
* @param op Pointer to arc connect operation
* @return Result of arc connect command
*/
static uint32_t arc_connect_cmd_execute(ARC_CONNECT_OP_T *op)
{
uint32_t regval = 0;
if (!op) {
return 0;
}
regval = op->cmd | ((op->param) << 8);
arc_spinlock_get(&arc_connect_lock);
switch (op->type) {
case ARC_CONNECT_CMD_TYPE_CMD_ONLY:
arc_aux_write(AUX_CONNECT_CMD, regval);
break;
case ARC_CONNECT_CMD_TYPE_CMD_RETURN:
arc_aux_write(AUX_CONNECT_CMD, regval);
break;
case ARC_CONNECT_CMD_TYPE_CMD_WDATA:
arc_aux_write(AUX_CONNECT_WDATA, op->wdata);
arc_aux_write(AUX_CONNECT_CMD, regval);
break;
case ARC_CONNECT_CMD_TYPE_CMD_WDATA_RETURN:
arc_aux_write(AUX_CONNECT_WDATA, op->wdata);
arc_aux_write(AUX_CONNECT_CMD, regval);
break;
default:
break;
}
regval = arc_aux_read(AUX_CONNECT_READBACK);
arc_spinlock_release(&arc_connect_lock);
return regval;
}
/**
* @brief Get the core id in arc connect
*
* @return Core id
*/
uint32_t arc_connect_check_core_id(void)
{
ARC_CONNECT_OP_T op;
ARC_CONNECT_CMD_RETURN_OP_SET(&op, ARC_CONNECT_CMD_CHECK_CORE_ID, 0);
return arc_connect_cmd_execute(&op);
}
/**
* @brief Enable interrupt distribute unit
*
*/
void arc_connect_idu_enable(void)
{
ARC_CONNECT_OP_T op;
ARC_CONNECT_CMD_ONLY_OP_SET(&op, ARC_CONNECT_CMD_IDU_ENABLE, 0);
arc_connect_cmd_execute(&op);
}
/**
* @brief Disable interrupt distribute unit
*
*/
void arc_connect_idu_disable(void)
{
ARC_CONNECT_OP_T op;
ARC_CONNECT_CMD_ONLY_OP_SET(&op, ARC_CONNECT_CMD_IDU_DISABLE, 0);
arc_connect_cmd_execute(&op);
}
/**
* @brief Read interrupt distribute enable status
*
* @return Enable status
*/
uint32_t arc_connect_idu_read_enable(void)
{
ARC_CONNECT_OP_T op;
ARC_CONNECT_CMD_RETURN_OP_SET(&op, ARC_CONNECT_CMD_IDU_READ_ENABLE, 0);
return arc_connect_cmd_execute(&op);
}
/**
* @brief Set the mode of irq connected to idu
*
* @param irq_num Number of irq connected to idu
* @param trigger_mode Trigger mode, level or pulse
* @param distri_mode Distribute mode
*/
void arc_connect_idu_set_mode(uint32_t irq_num, uint16_t trigger_mode, uint16_t distri_mode)
{
ARC_CONNECT_OP_T op;
ARC_CONNECT_CMD_WDATA_OP_SET(&op, ARC_CONNECT_CMD_IDU_SET_MODE, \
irq_num, (distri_mode | (trigger_mode << 4)));
arc_connect_cmd_execute(&op);
}
/**
* @brief Read the mode of irq connected to idu
*
* @param irq_num Number of irq connected to idu
*
*/
uint32_t arc_connect_idu_read_mode(uint32_t irq_num)
{
ARC_CONNECT_OP_T op;
ARC_CONNECT_CMD_RETURN_OP_SET(&op, ARC_CONNECT_CMD_IDU_READ_ENABLE, irq_num);
return arc_connect_cmd_execute(&op);
}
/**
* @brief Set the target core to handle the irq connected to idu
*
* @param irq_num Number of irq connected to idu
* @param target_core Target core
*/
void arc_connect_idu_set_dest(uint32_t irq_num, uint32_t target_core)
{
ARC_CONNECT_OP_T op;
ARC_CONNECT_CMD_WDATA_OP_SET(&op, ARC_CONNECT_CMD_IDU_SET_DEST, irq_num, target_core);
arc_connect_cmd_execute(&op);
}
/**
* @brief Read the target core to handle the irq connected to idu
*
* @param irq_num Number of irq connected to idu
* @return Target core
*/
uint32_t arc_connect_idu_read_dest(uint32_t irq_num)
{
ARC_CONNECT_OP_T op;
ARC_CONNECT_CMD_RETURN_OP_SET(&op, ARC_CONNECT_CMD_IDU_READ_DEST, irq_num);
return arc_connect_cmd_execute(&op);
}
/**
* @brief Generate the irq connected to idu in software
*
* @param irq_num Number of irq connected to idu
*/
void arc_connect_idu_gen_cirq(uint32_t irq_num)
{
ARC_CONNECT_OP_T op;
ARC_CONNECT_CMD_ONLY_OP_SET(&op, ARC_CONNECT_CMD_IDU_GEN_CIRQ, irq_num);
arc_connect_cmd_execute(&op);
}
/**
* @brief Acknowledge irq connected to idu
*
* @param irq_num Number of irq connected to idu
*/
void arc_connect_idu_ack_cirq(uint32_t irq_num)
{
ARC_CONNECT_OP_T op;
ARC_CONNECT_CMD_ONLY_OP_SET(&op, ARC_CONNECT_CMD_IDU_ACK_CIRQ, irq_num);
arc_connect_cmd_execute(&op);
}
/**
* @brief Check the status of irq connected to idu
*
* @param irq_num Number of irq connected to idu
* @return Status of irq connected to idu
*/
uint32_t arc_connect_idu_check_status(uint32_t irq_num)
{
ARC_CONNECT_OP_T op;
ARC_CONNECT_CMD_RETURN_OP_SET(&op, ARC_CONNECT_CMD_IDU_CHECK_STATUS, irq_num);
return arc_connect_cmd_execute(&op);
}
/**
* @brief Check the source of irq connected to idu
*
* @param irq_num Number of irq connected to idu
* @return Source of irq connected to idu
*/
uint32_t arc_connect_idu_check_source(uint32_t irq_num)
{
ARC_CONNECT_OP_T op;
ARC_CONNECT_CMD_RETURN_OP_SET(&op, ARC_CONNECT_CMD_IDU_CHECK_SOURCE, irq_num);
return arc_connect_cmd_execute(&op);
}
/**
* @brief Set the interrupt mask of irq connected to idu
*
* @param irq_num Number of irq connected to idu
* @param mask Interrupt mask
*/
void arc_connect_idu_set_mask(uint32_t irq_num, uint32_t mask)
{
ARC_CONNECT_OP_T op;
ARC_CONNECT_CMD_WDATA_OP_SET(&op, ARC_CONNECT_CMD_IDU_SET_MASK, irq_num, mask);
arc_connect_cmd_execute(&op);
}
/**
* @brief Read the interrupt mask of irq connected to idu
*
* @param irq_num Number of irq connected to idu
* @return Interrupt mask
*/
uint32_t arc_connect_idu_read_mask(uint32_t irq_num)
{
ARC_CONNECT_OP_T op;
ARC_CONNECT_CMD_RETURN_OP_SET(&op, ARC_CONNECT_CMD_IDU_READ_MASK, irq_num);
return arc_connect_cmd_execute(&op);
}
/**
* @brief Check the first core to handle the irq connected to idu
*
* @param irq_num Number of irq connected to idu
* @return Core number
*/
uint32_t arc_connect_idu_check_first(uint32_t irq_num)
{
ARC_CONNECT_OP_T op;
ARC_CONNECT_CMD_RETURN_OP_SET(&op, ARC_CONNECT_CMD_IDU_CHECK_FIRST, irq_num);
return arc_connect_cmd_execute(&op);
}
/**
* @brief Configure the irq connected to idu
*
* @param core Target core to handle the irq
* @param irq_num Number of irq connected to idu
* @param trigger_mode Trigger mode
* @param distri_mode Distribute mode
*/
void arc_connect_idu_config_irq(uint32_t core, uint32_t irq_num, uint16_t trigger_mode, uint16_t distri_mode)
{
arc_connect_idu_disable();
arc_connect_idu_set_mode(irq_num, trigger_mode, distri_mode);
arc_connect_idu_set_dest(irq_num, core);
arc_connect_idu_set_mask(irq_num, 0x0);
arc_connect_idu_enable();
}
/**
* @brief generate inter-core interrupt
* the calling core will raise an interrupt to the target core
* @param core_id the target core
*/
void arc_connect_ici_generate(uint32_t core_id)
{
ARC_CONNECT_OP_T op;
ARC_CONNECT_CMD_ONLY_OP_SET(&op, ARC_CONNECT_CMD_INTRPT_GENERATE_IRQ, core_id);
arc_connect_cmd_execute(&op);
}
/**
* @brief acknowledge the raised inter-core interrupt
*
* @param core_id the core rasing the inter-core interrupt
*/
void arc_connect_ici_ack(uint32_t core_id)
{
ARC_CONNECT_OP_T op;
ARC_CONNECT_CMD_ONLY_OP_SET(&op, ARC_CONNECT_CMD_INTRPT_GENERATE_ACK, core_id);
arc_connect_cmd_execute(&op);
}
/**
* @brief read the status of inter-core interrupt
*
* @param core_id the target core
* @return 1 the inter-core interrupt is pending, 0 the inter-core interrupt
* is acknowledged
*/
uint32_t arc_connect_ici_read_status(uint32_t core_id)
{
ARC_CONNECT_OP_T op;
ARC_CONNECT_CMD_RETURN_OP_SET(&op, ARC_CONNECT_CMD_INTRPT_READ_STATUS, core_id);
return arc_connect_cmd_execute(&op);
}
/**
* @brief check the source of inter-core interrupt
*
* @return the source of inter-core interrupt
*/
uint32_t arc_connect_ici_check_src(void)
{
ARC_CONNECT_OP_T op;
ARC_CONNECT_CMD_RETURN_OP_SET(&op, ARC_CONNECT_CMD_INTRPT_CHECK_SOURCE, 0);
return arc_connect_cmd_execute(&op);
}
/**
* @brief taka a inter-core semaphore
*
* @param sem_id semaphore id
* @return 0 failed, 1 success
*/
uint32_t arc_connect_ics_take(uint32_t sem_id)
{
ARC_CONNECT_OP_T op;
ARC_CONNECT_CMD_RETURN_OP_SET(&op, ARC_CONNECT_CMD_SEMA_CLAIM_AND_READ, sem_id);
return arc_connect_cmd_execute(&op);
}
/**
* @brief release a inter-core semaphore
*
* @param sem_id semaphore id
*/
void arc_connect_ics_release(uint32_t sem_id)
{
ARC_CONNECT_OP_T op;
ARC_CONNECT_CMD_ONLY_OP_SET(&op, ARC_CONNECT_CMD_SEMA_RELEASE, sem_id);
arc_connect_cmd_execute(&op);
}
/**
* @brief compulsively release and make available a semaphore
*
* @param sem_id semaphore id
*/
void arc_connect_ics_force_release(uint32_t sem_id)
{
ARC_CONNECT_OP_T op;
ARC_CONNECT_CMD_ONLY_OP_SET(&op, ARC_CONNECT_CMD_SEMA_FORCE_RELEASE, sem_id);
arc_connect_cmd_execute(&op);
}
/**
* @brief set the address of message-passing sram for subsequent read or
write sram operations
*
* @param addr sram address
*/
void arc_connect_icm_addr_set(uint32_t addr)
{
ARC_CONNECT_OP_T op;
ARC_CONNECT_CMD_ONLY_OP_SET(&op, ARC_CONNECT_CMD_MSG_SRAM_SET_ADDR, addr);
arc_connect_cmd_execute(&op);
}
/**
* @brief read the value of internal MSG_ADDR reg
*
* @return value of MSG_ADDR reg
*/
uint32_t arc_connect_icm_addr_read(void)
{
ARC_CONNECT_OP_T op;
ARC_CONNECT_CMD_RETURN_OP_SET(&op, ARC_CONNECT_CMD_MSG_SRAM_READ_ADDR, 0);
return arc_connect_cmd_execute(&op);
}
/**
* @brief set the offset address of message-passing sram for subsequent read or
write sram operations
*
* @param offset address offset
*/
void arc_connect_icm_addr_offset_set(uint32_t offset)
{
ARC_CONNECT_OP_T op;
ARC_CONNECT_CMD_ONLY_OP_SET(&op, ARC_CONNECT_CMD_MSG_SRAM_SET_ADDR_OFFSET, offset);
arc_connect_cmd_execute(&op);
}
/**
* @brief read the value of address offset reg
*
* @return value of address offset reg
*/
uint32_t arc_connect_icm_addr_offset_read(void)
{
ARC_CONNECT_OP_T op;
ARC_CONNECT_CMD_RETURN_OP_SET(&op, ARC_CONNECT_CMD_MSG_SRAM_READ_ADDR_OFFSET, 0);
return arc_connect_cmd_execute(&op);
}
/**
* @brief write data to the message-passing sram
*
* @param data data to write
*/
void arc_connect_icm_msg_write(uint32_t data)
{
ARC_CONNECT_OP_T op;
ARC_CONNECT_CMD_WDATA_OP_SET(&op, ARC_CONNECT_CMD_MSG_SRAM_WRITE, 0, data);
arc_connect_cmd_execute(&op);
}
/**
* @brief incremental write to the message-passing sram
*
* @param data data to write
*/
void arc_connect_icm_msg_inc_write(uint32_t data)
{
ARC_CONNECT_OP_T op;
ARC_CONNECT_CMD_WDATA_OP_SET(&op, ARC_CONNECT_CMD_MSG_SRAM_WRITE_INC, 0, data);
arc_connect_cmd_execute(&op);
}
/**
* @brief write data into the message passing sram with the address
* specified by an immediate value.
*
* @param addr the specified address
* @param data data to write
*/
void arc_connect_icm_msg_imm_write(uint32_t addr, uint32_t data)
{
ARC_CONNECT_OP_T op;
ARC_CONNECT_CMD_WDATA_OP_SET(&op, ARC_CONNECT_CMD_MSG_SRAM_WRITE_IMM, addr, data);
arc_connect_cmd_execute(&op);
}
/**
* @brief read data from the message passing sram
*
* @return read data
*/
uint32_t arc_connect_icm_msg_read(void)
{
ARC_CONNECT_OP_T op;
ARC_CONNECT_CMD_RETURN_OP_SET(&op, ARC_CONNECT_CMD_MSG_SRAM_READ, 0);
return arc_connect_cmd_execute(&op);
}
/**
* @brief incremental read data from the message passing sram
*
* @return read data
*/
uint32_t arc_connect_icm_msg_inc_read(void)
{
ARC_CONNECT_OP_T op;
ARC_CONNECT_CMD_RETURN_OP_SET(&op, ARC_CONNECT_CMD_MSG_SRAM_READ_INC, 0);
return arc_connect_cmd_execute(&op);
}
/**
* @brief read data at the specified address from the message passing sram
*
* @param addr the specified address
* @return read data
*/
uint32_t arc_connect_icm_msg_imm_read(uint32_t addr)
{
ARC_CONNECT_OP_T op;
ARC_CONNECT_CMD_RETURN_OP_SET(&op, ARC_CONNECT_CMD_MSG_SRAM_READ_IMM, addr);
return arc_connect_cmd_execute(&op);
}
/**
* @brief enable or disable ECC or parity protection on the message data
*
* @param val 0 = enable protection, 1= disable protection
*/
void arc_connect_icm_ecc_ctrl_set(uint32_t val)
{
ARC_CONNECT_OP_T op;
ARC_CONNECT_CMD_WDATA_OP_SET(&op, ARC_CONNECT_CMD_MSG_SRAM_SET_ECC_CTRL, 0, val);
arc_connect_cmd_execute(&op);
}
/**
* @brief read the status ofECC or parity protection on the message data
*
* @return 0 = enable protection, 1= disable protection
*/
uint32_t arc_connect_icm_ecc_ctrl_read(void)
{
ARC_CONNECT_OP_T op;
ARC_CONNECT_CMD_RETURN_OP_SET(&op, ARC_CONNECT_CMD_MSG_SRAM_READ_ECC_CTRL, 0);
return arc_connect_cmd_execute(&op);
}
/**
* @brief generate reset request to cores in the system.
*
* @param cores the target cores
*/
void arc_connect_debug_reset(uint32_t cores)
{
ARC_CONNECT_OP_T op;
ARC_CONNECT_CMD_WDATA_OP_SET(&op, ARC_CONNECT_CMD_DEBUG_RESET, 0, cores);
arc_connect_cmd_execute(&op);
}
/**
* @brief generate halt request to cores in the system.
*
* @param cores the target cores
*/
void arc_connect_debug_halt(uint32_t cores)
{
ARC_CONNECT_OP_T op;
ARC_CONNECT_CMD_WDATA_OP_SET(&op, ARC_CONNECT_CMD_DEBUG_HALT, 0, cores);
arc_connect_cmd_execute(&op);
}
/**
* @brief generate run request to cores in the system.
*
* @param cores the target cores
*/
void arc_connect_debug_run(uint32_t cores)
{
ARC_CONNECT_OP_T op;
ARC_CONNECT_CMD_WDATA_OP_SET(&op, ARC_CONNECT_CMD_DEBUG_RUN, 0, cores);
arc_connect_cmd_execute(&op);
}
/**
* @brief set the internal MASK reg in ICD
* the MASK register determines whether a global halt is triggered
* if a core is halted in response to one of the following events:
* core halt, actionpoint halt, self-halt, and breakpoint halt
* @param cores the cores for which the MASK register should be updated
* @param mask mask bits
*/
void arc_connect_debug_mask_set(uint32_t cores, uint32_t mask)
{
ARC_CONNECT_OP_T op;
ARC_CONNECT_CMD_WDATA_OP_SET(&op, ARC_CONNECT_CMD_DEBUG_SET_MASK, mask, cores);
arc_connect_cmd_execute(&op);
}
/**
* @brief read the internal MASK reg in ICD
*
* @param cores the cores for which the MASK register should be read
* @return mask bits
*/
uint32_t arc_connect_debug_mask_read(uint32_t cores)
{
ARC_CONNECT_OP_T op;
ARC_CONNECT_CMD_WDATA_OP_SET(&op, ARC_CONNECT_CMD_DEBUG_RUN, 0, cores);
return arc_connect_cmd_execute(&op);
}
/**
* @brief select cores that should be halted if the core issuing the command is halted
*
* @param cores cores to select
*/
void arc_connect_debug_select_set(uint32_t cores)
{
ARC_CONNECT_OP_T op;
ARC_CONNECT_CMD_WDATA_OP_SET(&op, ARC_CONNECT_CMD_DEBUG_SET_SELECT, 0, cores);
arc_connect_cmd_execute(&op);
}
/**
* @brief ead the internal SELECT register in ICD
*
* @return SELECT register value
*/
uint32_t arc_connect_debug_select_read(void)
{
ARC_CONNECT_OP_T op;
ARC_CONNECT_CMD_RETURN_OP_SET(&op, ARC_CONNECT_CMD_DEBUG_READ_SELECT, 0);
return arc_connect_cmd_execute(&op);
}
/**
* @brief read the status, halt or run,of all cores
*
* @return bits: 1 running, 0 halted
*/
uint32_t arc_connect_debug_en_read(void)
{
ARC_CONNECT_OP_T op;
ARC_CONNECT_CMD_RETURN_OP_SET(&op, ARC_CONNECT_CMD_DEBUG_READ_EN, 0);
return arc_connect_cmd_execute(&op);
}
/**
* @brief check the last command sent to ICD.
*
* @return ICD command
*/
uint32_t arc_connect_debug_cmd_read(void)
{
ARC_CONNECT_OP_T op;
ARC_CONNECT_CMD_RETURN_OP_SET(&op, ARC_CONNECT_CMD_DEBUG_READ_CMD, 0);
return arc_connect_cmd_execute(&op);
}
/**
* @brief read the value of internal MCD_CORE register in ICD
*
* @return MCD_CORE register
*/
uint32_t arc_connect_debug_core_read(void)
{
ARC_CONNECT_OP_T op;
ARC_CONNECT_CMD_RETURN_OP_SET(&op, ARC_CONNECT_CMD_DEBUG_READ_CORE, 0);
return arc_connect_cmd_execute(&op);
}
/**
* @brief clear the global free running counter
*
*/
void arc_connect_gfrc_clear(void)
{
ARC_CONNECT_OP_T op;
ARC_CONNECT_CMD_ONLY_OP_SET(&op, ARC_CONNECT_CMD_GFRC_CLEAR, 0);
arc_connect_cmd_execute(&op);
}
/**
* @brief read low 32-bit of gfrc
*
* @return low 32-bit of gfrc
*/
uint32_t arc_connect_gfrc_lo_read(void)
{
ARC_CONNECT_OP_T op;
ARC_CONNECT_CMD_RETURN_OP_SET(&op, ARC_CONNECT_CMD_GFRC_READ_LO, 0);
return arc_connect_cmd_execute(&op);
}
/**
* @brief read high 32-bit of gfrc
*
* @return high 32-bit of gfrc
*/
uint32_t arc_connect_gfrc_hi_read(void)
{
ARC_CONNECT_OP_T op;
ARC_CONNECT_CMD_RETURN_OP_SET(&op, ARC_CONNECT_CMD_GFRC_READ_HI, 0);
return arc_connect_cmd_execute(&op);
}
/**
* @brief enable gfrc
*
*/
void arc_connect_gfrc_enable(void)
{
ARC_CONNECT_OP_T op;
ARC_CONNECT_CMD_ONLY_OP_SET(&op, ARC_CONNECT_CMD_GFRC_ENABLE, 0);
arc_connect_cmd_execute(&op);
}
/**
* @brief disable gfrc
*
*/
void arc_connect_gfrc_disable(void)
{
ARC_CONNECT_OP_T op;
ARC_CONNECT_CMD_ONLY_OP_SET(&op, ARC_CONNECT_CMD_GFRC_DISABLE, 0);
arc_connect_cmd_execute(&op);
}
/**
* @brief set the relevant cores to halt the GFRC
*
* @param cores the relevant cores
*/
void arc_connect_gfrc_core_set(uint32_t cores)
{
ARC_CONNECT_OP_T op;
ARC_CONNECT_CMD_WDATA_OP_SET(&op, ARC_CONNECT_CMD_GFRC_SET_CORE, 0, cores);
arc_connect_cmd_execute(&op);
}
/**
* @brief read the status of gfrc
*
* @return gfrc status
*/
uint32_t arc_connect_gfrc_halt_read(void)
{
ARC_CONNECT_OP_T op;
ARC_CONNECT_CMD_RETURN_OP_SET(&op, ARC_CONNECT_CMD_GFRC_READ_HALT, 0);
return arc_connect_cmd_execute(&op);
}
/**
* @brief read the internal CORE register
*
* @return CORE register value
*/
uint32_t arc_connect_gfrc_core_read(void)
{
ARC_CONNECT_OP_T op;
ARC_CONNECT_CMD_RETURN_OP_SET(&op, ARC_CONNECT_CMD_GFRC_READ_CORE, 0);
return arc_connect_cmd_execute(&op);
}
/**
* @brief set the power mode for specific ARConnect group
*
* @param group the ARConnect group
* @param cmd power mode
*/
void arc_connect_pdm_pm_set(uint32_t group, uint32_t cmd)
{
ARC_CONNECT_OP_T op;
ARC_CONNECT_CMD_WDATA_OP_SET(&op, ARC_CONNECT_CMD_PDM_SET_PM, group, cmd);
arc_connect_cmd_execute(&op);
}
/**
* @brief read the internal PM register of the specified ARConnect group.
*
* @param group the ARConnect group
* @return status value
*/
uint32_t arc_connect_pdm_pdstatus_read(uint32_t group)
{
ARC_CONNECT_OP_T op;
ARC_CONNECT_CMD_RETURN_OP_SET(&op, ARC_CONNECT_CMD_PDM_READ_PSTATUS, group);
return arc_connect_cmd_execute(&op);
}
/**
* @brief set PUCNT
*
* @param cnt cnt to set
*/
void arc_connect_pmu_pucnt_set(uint32_t cnt)
{
ARC_CONNECT_OP_T op;
ARC_CONNECT_CMD_WDATA_OP_SET(&op, ARC_CONNECT_CMD_PMU_SET_PUCNT, 0, cnt);
arc_connect_cmd_execute(&op);
}
/**
* @brief read the PUNCNT
*
* @return PUNCNT's value
*/
uint32_t arc_connect_pmu_pucnt_read(void)
{
ARC_CONNECT_OP_T op;
ARC_CONNECT_CMD_RETURN_OP_SET(&op, ARC_CONNECT_CMD_PMU_READ_PUCNT, 0);
return arc_connect_cmd_execute(&op);
}
/**
* @brief set RSTCNT
*
* @param cnt cnt to set
*/
void arc_connect_pmu_rstcnt_set(uint32_t cnt)
{
ARC_CONNECT_OP_T op;
ARC_CONNECT_CMD_WDATA_OP_SET(&op, ARC_CONNECT_CMD_PMU_SET_RSTCNT, 0, cnt);
arc_connect_cmd_execute(&op);
}
/**
* @brief read RSTCNT
*
* @return RSTCNT's value
*/
uint32_t arc_connect_pmu_rstcnt_read(void)
{
ARC_CONNECT_OP_T op;
ARC_CONNECT_CMD_RETURN_OP_SET(&op, ARC_CONNECT_CMD_PMU_READ_RSTCNT, 0);
return arc_connect_cmd_execute(&op);
}
/**
* @brief set PDCCNT
*
* @param cnt cnt to set
*/
void arc_connect_pmu_pdccnt_set(uint32_t cnt)
{
ARC_CONNECT_OP_T op;
ARC_CONNECT_CMD_WDATA_OP_SET(&op, ARC_CONNECT_CMD_PMU_SET_PDCNT, 0, cnt);
arc_connect_cmd_execute(&op);
}
/**
* @brief read PDCCNT
*
* @return PDCCNT's vaule
*/
uint32_t arc_connect_pmu_pdccnt_read(void)
{
ARC_CONNECT_OP_T op;
ARC_CONNECT_CMD_RETURN_OP_SET(&op, ARC_CONNECT_CMD_PMU_READ_PDCNT, 0);
return arc_connect_cmd_execute(&op);
}

View File

@@ -1,159 +0,0 @@
/* ------------------------------------------
* 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.
*
--------------------------------------------- */
/**
* @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 "arc/arc.h"
#include "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
/* 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]
/* jump to exception handler where interrupts are not allowed! */
mov r0, sp
jl [r2]
exc_return:
EXCEPTION_EPILOGUE
rtie
/****** entry for normal interrupt exception handling ******/
.global exc_entry_int
.weak exc_entry_int
.align 4
exc_entry_int:
#if ARC_FEATURE_FIRQ == 1
#if ARC_FEATURE_RGF_NUM_BANKS > 1
/* check whether it is P0 interrupt */
lr r0, [AUX_IRQ_ACT]
btst r0, 0
bnz exc_entry_firq
#else
PUSH r10
lr r10, [AUX_IRQ_ACT]
btst r10, 0
POP r10
bnz exc_entry_firq
#endif
#endif
/* save scratch regs */
INTERRUPT_PROLOGUE
/* critical area */
lr r0, [AUX_IRQ_CAUSE]
mov r1, exc_int_handler_table
/* r2 = _kernel_exc_tbl + irqno *4 */
ld.as r2, [r1, r0]
/* 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:
/* jump to interrupt handler */
mov r0, sp
jl [r2]
int_return:
INTERRUPT_EPILOGUE
rtie
/****** entry for fast irq exception handling ******/
.global exc_entry_firq
.weak exc_entry_firq
.align 4
exc_entry_firq:
SAVE_FIQ_EXC_REGS
lr r0, [AUX_IRQ_CAUSE]
mov r1, exc_int_handler_table
/* r2 = _kernel_exc_tbl + irqno *4 */
ld.as r2, [r1, r0]
/* for the case of software triggered interrupt */
lr r3, [AUX_IRQ_HINT]
cmp r3, r0
bne.d firq_hint_handled
xor r3, r3, r3
sr r3, [AUX_IRQ_HINT]
firq_hint_handled:
/* jump to interrupt handler */
mov r0, sp
jl [r2]
firq_return:
RESTORE_FIQ_EXC_REGS
rtie
/** @endcond */

View File

@@ -1,812 +0,0 @@
/* ------------------------------------------
* 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.
*
--------------------------------------------- */
/**
* @file
* @ingroup ARC_HAL_EXCEPTION_CPU ARC_HAL_EXCEPTION_INTERRUPT
* @brief ARC interrupt and exception handling
*/
#include "arc/arc_exception.h"
#include "arc/arc_cache.h"
#define DBG_LESS
#include "embARC_debug.h"
/**
* @addtogroup ARC_HAL_EXCEPTION_CPU
* @{
* @var EXC_ENTRY_T 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.
*
*/
#ifdef CONFIG_ARC_EXCEPTION_DEBUG
/* For EV_ProtV, the numbering/semantics of the parameter are consistent across
* several codes, although not all combination will be reported.
*
* These codes and parameters do not have associated* names in
* the technical manual, just switch on the values in Table 6-5
*/
static void dump_protv_access_err(uint32_t parameter)
{
switch (parameter) {
case 0x1:
EMBARC_PRINTF("code protection scheme");
break;
case 0x2:
EMBARC_PRINTF("stack checking scheme");
break;
case 0x4:
EMBARC_PRINTF("MPU");
break;
case 0x8:
EMBARC_PRINTF("MMU");
break;
case 0x10:
EMBARC_PRINTF("NVM");
break;
case 0x24:
EMBARC_PRINTF("Secure MPU");
break;
case 0x44:
EMBARC_PRINTF("Secure MPU with SID mismatch");
break;
default:
EMBARC_PRINTF("unknown parameter");
break;
}
}
static void dump_protv_exception(uint32_t cause, uint32_t parameter)
{
switch (cause) {
case 0x0:
EMBARC_PRINTF("Instruction fetch violation: ");
dump_protv_access_err(parameter);
break;
case 0x1:
EMBARC_PRINTF("Memory read protection violation: ");
dump_protv_access_err(parameter);
break;
case 0x2:
EMBARC_PRINTF("Memory write protection violation: ");
dump_protv_access_err(parameter);
break;
case 0x3:
EMBARC_PRINTF("Memory read-modify-write violation: ");
dump_protv_access_err(parameter);
break;
case 0x10:
EMBARC_PRINTF("Normal vector table in secure memory");
break;
case 0x11:
EMBARC_PRINTF("NS handler code located in S memory");
break;
case 0x12:
EMBARC_PRINTF("NSC Table Range Violation");
break;
default:
EMBARC_PRINTF("unknown cause");
break;
}
}
static void dump_machine_check_exception(uint32_t cause, uint32_t parameter)
{
switch (cause) {
case 0x0:
EMBARC_PRINTF("double fault");
break;
case 0x1:
EMBARC_PRINTF("overlapping TLB entries");
break;
case 0x2:
EMBARC_PRINTF("fatal TLB error");
break;
case 0x3:
EMBARC_PRINTF("fatal cache error");
break;
case 0x4:
EMBARC_PRINTF("internal memory error on instruction fetch");
break;
case 0x5:
EMBARC_PRINTF("internal memory error on data fetch");
break;
case 0x6:
EMBARC_PRINTF("illegal overlapping MPU entries");
if (parameter == 0x1) {
EMBARC_PRINTF(" (jump and branch target)");
}
break;
case 0x10:
EMBARC_PRINTF("secure vector table not located in secure memory");
break;
case 0x11:
EMBARC_PRINTF("NSC jump table not located in secure memory");
break;
case 0x12:
EMBARC_PRINTF("secure handler code not located in secure memory");
break;
case 0x13:
EMBARC_PRINTF("NSC target address not located in secure memory");
break;
case 0x80:
EMBARC_PRINTF("uncorrectable ECC or parity error in vector memory");
break;
default:
EMBARC_PRINTF("unknown cause");
break;
}
}
static void dump_privilege_exception(uint32_t cause, uint32_t parameter)
{
switch (cause) {
case 0x0:
EMBARC_PRINTF("Privilege violation");
break;
case 0x1:
EMBARC_PRINTF("disabled extension");
break;
case 0x2:
EMBARC_PRINTF("action point hit");
break;
case 0x10:
switch (parameter) {
case 0x1:
EMBARC_PRINTF("N to S return using incorrect return mechanism");
break;
case 0x2:
EMBARC_PRINTF("N to S return with incorrect operating mode");
break;
case 0x3:
EMBARC_PRINTF("IRQ/exception return fetch from wrong mode");
break;
case 0x4:
EMBARC_PRINTF("attempt to halt secure processor in NS mode");
break;
case 0x20:
EMBARC_PRINTF("attempt to access secure resource from normal mode");
break;
case 0x40:
EMBARC_PRINTF("SID violation on resource access (APEX/UAUX/key NVM)");
break;
default:
EMBARC_PRINTF("unknown parameter");
break;
}
break;
case 0x13:
switch (parameter) {
case 0x20:
EMBARC_PRINTF("attempt to access secure APEX feature from NS mode");
break;
case 0x40:
EMBARC_PRINTF("SID violation on access to APEX feature");
break;
default:
EMBARC_PRINTF("unknown parameter");
break;
}
break;
default:
EMBARC_PRINTF("unknown cause");
break;
}
}
static void dump_exception_info(uint32_t vector, uint32_t cause, uint32_t param)
{
/* Names are exactly as they appear in Designware ARCv2 ISA
* Programmer's reference manual for easy searching
*/
switch (vector) {
case EXC_NO_RESET:
EMBARC_PRINTF("Reset");
break;
case EXC_NO_MEM_ERR:
EMBARC_PRINTF("Memory Error");
break;
case EXC_NO_INS_ERR:
EMBARC_PRINTF("Instruction Error");
break;
case EXC_NO_MAC_CHK:
EMBARC_PRINTF("EV_MachineCheck: ");
dump_machine_check_exception(cause, param);
break;
case EXC_NO_TLB_MISS_I:
EMBARC_PRINTF("EV_TLBMissI");
break;
case EXC_NO_TLB_MISS_D:
EMBARC_PRINTF("EV_TLBMissD");
break;
case EXC_NO_PRO_VIO:
EMBARC_PRINTF("EV_ProtV: ");
dump_protv_exception(cause, param);
break;
case EXC_NO_PRI_VIO:
EMBARC_PRINTF("EV_PrivilegeV: ");
dump_privilege_exception(cause, param);
break;
case EXC_NO_SWI:
EMBARC_PRINTF("EV_SWI");
break;
case EXC_NO_TRAP:
EMBARC_PRINTF("EV_Trap");
break;
case EXC_NO_EXT:
EMBARC_PRINTF("EV_Extension");
break;
case EXC_NO_DIV_ZER0:
EMBARC_PRINTF("EV_DivZero");
break;
case EXC_NO_DC_ERR:
EMBARC_PRINTF("EV_DCError");
break;
case EXC_NO_MAL_ALIGN:
EMBARC_PRINTF("EV_Misaligned");
break;
case EXC_NO_VEC_UNIT:
EMBARC_PRINTF("EV_VecUnit");
break;
default:
EMBARC_PRINTF("unknown exception vector");
break;
}
EMBARC_PRINTF("\n");
}
#endif /* CONFIG_ARC_EXCEPTION_DEBUG */
/**
* @ingroup ARC_HAL_EXCEPTION_CPU
* @brief Install 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;
uint32_t exc_cause = 0;
uint32_t exc_param = 0;
excpt_cause_reg = arc_aux_read(AUX_ECR);
excpt_ret_reg = arc_aux_read(AUX_ERRET);
exc_no = (excpt_cause_reg >> 16) & 0xff;
exc_cause = (excpt_cause_reg >> 8) & 0xff;
exc_param = (excpt_cause_reg >> 0) & 0xff;
dbg_printf(DBG_LESS_INFO, "default cpu exception handler\r\n");
dbg_printf(DBG_LESS_INFO, "exc_no:%d, last sp:0x%08x, ecr:0x%08x, eret:0x%08x\r\n",
exc_no, p_excinf, excpt_cause_reg, excpt_ret_reg);
#ifdef CONFIG_ARC_EXCEPTION_DEBUG
dump_exception_info(exc_no, exc_cause, exc_param);
#endif
#ifndef EMBARC_UNIT_TEST
arc_kflag(1);
#endif
}
/**
* @ingroup ARC_HAL_EXCEPTION_INTERRUPT
* @brief Register default interrupt handler
* @param p_excinf Information for interrupt handler
*/
static void int_handler_default(void *p_excinf)
{
uint32_t int_cause_reg = 0;
int_cause_reg = arc_aux_read(AUX_IRQ_CAUSE);
dbg_printf(DBG_LESS_INFO, "default interrupt handler\r\n");
dbg_printf(DBG_LESS_INFO, "last sp:0x%08x, icause:0x%08x\r\n", p_excinf, int_cause_reg);
arc_kflag(1);
}
/* Enforcement of 1024 byte alignment */
__attribute__ ((aligned(1024), section(".vector")))
/**
* @cond Doxygen_Suppress
*/
EXC_ENTRY_T exc_entry_table[NUM_EXC_ALL] = { [0] = exc_entry_reset,
[1 ... NUM_EXC_CPU - 1] = exc_entry_cpu,
[NUM_EXC_CPU ... NUM_EXC_ALL - 1] = exc_entry_int
};
/**
* @var EXC_HANDLER_T exc_int_handler_table
* @brief CPU exception and interrupt exception handler table
* called in exc_entry_default and exc_entry_int
*/
EXC_HANDLER_T 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
};
/**
* @endcond
*/
typedef struct {
/* 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;
extern uint8_t _f_stack[];
/**
* @ingroup ARC_HAL_EXCEPTION_INTERRUPT
* @brief Initialize 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 */
#if ARC_FEATURE_CODE_DENSITY
ictrl.bits.save_idx_regs = 1; /* JLI, LDI, EI */
#endif
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)
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));
#if ARC_FEATURE_RGF_BANKED_REGS >= 16 && ARC_FEATURE_FIRQ == 1
#if _STACKSIZE < 512
#error "not enough stack size for irq and firq"
#endif
/* top 256 bytes of stack used as firq stack */
arc_firq_stack_set(_f_stack + 256);
#endif
}
/**
* @ingroup ARC_HAL_EXCEPTION_CPU
* @brief Install a CPU exception entry
* @param excno Exception number
* @param entry Exception entry to install
*/
int32_t exc_entry_install(const uint32_t excno, EXC_ENTRY_T entry)
{
uint32_t status;
EXC_ENTRY_T *table;
#if defined(ARC_FEATURE_SEC_PRESENT)
table = (EXC_ENTRY_T *)arc_aux_read(AUX_INT_VECT_BASE_S);
#else
table = (EXC_ENTRY_T *)arc_aux_read(AUX_INT_VECT_BASE);
#endif
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 excno Exception number
* @return The installed CPU exception entry
*/
EXC_ENTRY_T 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 excno Exception number
* @param handler The installed CPU exception handler
*/
int32_t exc_handler_install(const uint32_t excno, EXC_HANDLER_T 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 excno Exception number
* @return The installed exception handler or NULL
*/
EXC_HANDLER_T 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 interrupt
*
* @param 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 interrupt
*
* @param 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 Get interrupt enable state
*
* @param 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 interrupt priority masking threshold
*
* @returns Interrupt priority masking threshold, negative num
*/
int32_t int_ipm_get(void)
{
return ((int32_t)arc_int_ipm_get() + INT_PRI_MIN);
}
/**
* @brief Set interrupt priority masking threshold
*
* @param intpri Interrupt priority masking threshold
*/
int32_t int_ipm_set(int32_t intpri)
{
if (intpri >= INT_PRI_MIN && intpri <= INT_PRI_MAX) {
arc_int_ipm_set(intpri - INT_PRI_MIN);
return 0;
}
return -1;
}
/**
* @brief Get current interrupt priority masking threshold
*
* @param 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 intno Interrupt number
* @param 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
* @param intno Interrupt number
* @param 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 interrupt pending state
*
* @param 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 interrupt through software
*
* @param 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 Configure interrupt trigger mode
*
* @param intno Interrupt number
* @param level 0-level triggered, 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 Get interrupt request mode
*
* @param intno Interrupt number
*/
int32_t int_level_get(const uint32_t intno)
{
if (intno >= NUM_EXC_CPU && intno < NUM_EXC_ALL) {
return (int32_t)arc_int_level_get(intno);
}
return -1;
}
/**
* @brief lock cpu, disable interrupts
*/
void cpu_lock(void)
{
arc_lock();
}
/**
* @brief Unlock cpu to enable interrupts
*/
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 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 interrupt handler
* @param intno Interrupt number
* @param handler Interrupt handler
*/
int32_t int_handler_install(const uint32_t intno, INT_HANDLER_T 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 interrupt handler
* @param intno Interrupt number
* @return The installed interrupt handler or NULL
*/
INT_HANDLER_T 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 */
/**
* @brief Set the stack pointer for firq handling
*
* @param firq_sp stack pointer
*/
void arc_firq_stack_set(uint8_t *firq_sp)
{
uint32_t status;
if (firq_sp == NULL) {
return;
}
status = arc_lock_save();
Asm(
/* only ilink will not be banked, so use ilink as channel
* between 2 banks
*/
"mov %%ilink, %0 \n\t"
"lr %0, [%1] \n\t"
"or %0, %0, %2 \n\t"
"kflag %0 \n\t"
"mov %%sp, %%ilink \n\t"
/* switch back to bank0, use ilink to avoid the pollution of
* bank1's gp regs.
*/
"lr %%ilink, [%1] \n\t"
"and %%ilink, %%ilink, %3 \n\t"
"kflag %%ilink \n\t"
:
: "r" (firq_sp), "i" (AUX_STATUS32),
"i" (AUX_STATUS_RB(1)),
"i" (~AUX_STATUS_RB(7))
);
arc_unlock_restore(status);
}
/** @} end of group ARC_HAL_EXCEPTION_CPU */

View File

@@ -1,89 +0,0 @@
/* ------------------------------------------
* 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.
*
--------------------------------------------- */
#include "arc/arc_mp.h"
static volatile struct {
void (*fn)(uint32_t, void *);
void *arg;
} arc_cpu_init[ARC_FEATURE_MP_NUM_CPUS];
/*
* arc_cpu_wake_flag is used to sync up master core and slave cores
* Slave core will spin for arc_cpu_wake_flag until master core sets
* it to the core id of slave core. Then, slave core clears it to notify
* master core that it's waken
*
*/
volatile uint32_t arc_cpu_wake_flag;
volatile uint8_t *arc_cpu_sp;
/**
* @brief Start slave cpu
* master core call this function to start slave cpu
* @param cpu_num Slave cpu number
* @param stack The pointer to stack area of slave cpu
* @param sz Stack size
* @param fn Function that slave cpu execute
* @param arg Argument for slave cpu
*/
void arc_start_slave_cpu(uint32_t cpu_num, uint8_t *stack, uint32_t sz,
void (*fn)(uint32_t, void *), void *arg)
{
arc_cpu_init[cpu_num].fn = fn;
arc_cpu_init[cpu_num].arg = arg;
/* set the initial sp of target sp through arc_cpu_sp
* arc_cpu_wake_flag will protect arc_cpu_sp that
* only one slave cpu can read it per time
*/
arc_cpu_sp = stack + sz;
arc_cpu_wake_flag = cpu_num;
/* wait slave cpu to start */
while (arc_cpu_wake_flag != 0) {
;
}
}
/**
* @brief The C entry of slave cpu
*
* @param cpu_num Slave cpu id
*/
void arc_slave_start(uint32_t cpu_num)
{
void (*fn)(uint32_t, void *);
fn = arc_cpu_init[cpu_num].fn;
fn(cpu_num, arc_cpu_init[cpu_num].arg);
}

View File

@@ -1,198 +0,0 @@
/* ------------------------------------------
* 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.
*
--------------------------------------------- */
#include "arc/arc_mpu.h"
#define CALC_REGION_END_ADDR(start, size) \
(start + size - (1 << ARC_FEATURE_MPU_ALIGNMENT_BITS))
/**
* @brief Enable the memory protection unit
*
*/
void arc_mpu_enable(void)
{
#if ARC_FEATURE_MPU_VERSION == 2
arc_aux_write(AUX_MPU_EN, arc_aux_read(AUX_MPU_EN) | AUX_MPU_EN_ENABLE);
#elif ARC_FEATURE_MPU_VERSION == 4
arc_mpu_default(0);
#endif
}
/**
* @brief Disable the memory protection unit
*
*/
void arc_mpu_disable(void)
{
#if ARC_FEATURE_MPU_VERSION == 2
arc_aux_write(AUX_MPU_EN, arc_aux_read(AUX_MPU_EN) & AUX_MPU_EN_DISABLE);
#elif ARC_FEATURE_MPU_VERSION == 4
arc_mpu_default(ARC_MPU_REGION_ALL_ATTR | AUX_MPU_ATTR_S | AUX_MPU_ATTR_SID(1));
#endif
}
/**
* @brief Configure the given mpu region
*
* @param index Region index to be configured
* @param base Base address for the region
* @param size Region size of the region to be configured
* @param region_attr Attribute value of mpu region
*/
void arc_mpu_region_config(uint32_t index, uint32_t base, uint32_t size, uint32_t region_attr)
{
if (index >= ARC_FEATURE_MPU_REGIONS) {
return;
}
region_attr &= AUX_MPU_ATTR_MASK;
/* ARC MPU version 2 and version 3 have different aux reg interface */
#if ARC_FEATURE_MPU_VERSION == 2
uint8_t bits = arc_find_msb(size) - 1;
if (bits < ARC_FEATURE_MPU_ALIGNMENT_BITS) {
bits = ARC_FEATURE_MPU_ALIGNMENT_BITS;
}
if ((1 << bits) < size) {
bits++;
}
if (size > 0) {
region_attr |= AUX_MPU_RDP_REGION_SIZE(bits);
base |= AUX_MPU_VALID_MASK;
} else {
base = 0;
}
arc_aux_write(2 * index + AUX_MPU_RDP0, region_attr);
arc_aux_write(2 * index + AUX_MPU_RDB0, base);
#elif ARC_FEATURE_MPU_VERSION == 4
if (size < (1 << ARC_FEATURE_MPU_ALIGNMENT_BITS)) {
size = (1 << ARC_FEATURE_MPU_ALIGNMENT_BITS);
}
if (region_attr) {
region_attr |= AUX_MPU_VALID_MASK;
}
arc_aux_write(AUX_MPU_INDEX, index);
arc_aux_write(AUX_MPU_RSTART, base);
arc_aux_write(AUX_MPU_REND, CALC_REGION_END_ADDR(base, size));
arc_aux_write(AUX_MPU_RPER, region_attr);
#endif
}
/**
* @brief Set default attribute of mpu region
*
* @param region_attr Attribute value
*/
void arc_mpu_default(uint32_t region_attr)
{
uint32_t val = arc_aux_read(AUX_MPU_EN) &
(~AUX_MPU_ATTR_MASK);
arc_aux_write(AUX_MPU_EN, (region_attr & AUX_MPU_ATTR_MASK) | val);
}
/**
* @brief Check whether [start, start+size] in the given mpu region
*
* @param index Region index
* @param start Start address of memory
* @param size Size of memory
* @return 1 in the given mpu region, 0 not in
*/
int32_t arc_mpu_in_region(uint32_t index, uint32_t start, uint32_t size)
{
#if ARC_FEATURE_MPU_VERSION == 2
uint32_t r_addr_start;
uint32_t r_addr_end;
uint32_t r_size_lshift;
r_addr_start = arc_aux_read(AUX_MPU_RDB0 + 2 * index) & (~AUX_MPU_VALID_MASK);
r_size_lshift = arc_aux_read(AUX_MPU_RDP0 + 2 * index) & AUX_MPU_ATTR_MASK;
r_size_lshift = (r_size_lshift & 0x3) | ((r_size_lshift >> 7) & 0x1C);
r_addr_end = r_addr_start + (1 << (r_size_lshift + 1));
if (start >= r_addr_start && (start + size) < r_addr_end) {
return 1;
}
#elif ARC_FEATURE_MPU_VERSION == 4
if ((index == arc_mpu_probe(start)) &&
(index == arc_mpu_probe(start + size))) {
return 1;
}
#endif
return 0;
}
/**
* @brief Probe whether the given address in mpu entries
*
* @param addr The given address
* @return -1 not in mpu entries, -2 mpu version error, >= 0 mpu entry number
*/
int32_t arc_mpu_probe(uint32_t addr)
{
#if ARC_FEATURE_MPU_VERSION == 2
uint32_t index;
uint32_t regions = ARC_FEATURE_MPU_REGIONS;
for (index = 0; index < regions; index++) {
if (arc_mpu_in_region(index, addr, 0)) {
return (int32_t)index;
}
}
return -1;
#elif ARC_FEATURE_MPU_VERSION == 4
uint32_t index;
arc_aux_write(AUX_MPU_PROBE, addr);
index = arc_aux_read(AUX_MPU_INDEX);
/* if no match or multiple regions match, return error */
if (index & (AUX_MPU_INDEX_DEFAULT | AUX_MPU_INDEX_MULT)) {
return -1;
} else {
return (int32_t)index;
}
#else
return -2;
#endif
}

View File

@@ -1,447 +0,0 @@
/* ------------------------------------------
* 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.
*
--------------------------------------------- */
/**
* @file
* @ingroup ARC_HAL_MISC_TIMER
* @brief Internal timer implementation
* @todo RTC support should be improved if RTC is enabled
*/
#include "arc/arc_timer.h"
#include "arc/arc_exception.h"
#define LPS_PREC 8
static volatile uint64_t gl_loops_per_jiffy = 1;
static volatile uint32_t gl_count = 1;
/**
* @brief Check whether the specific timer present
* @param no Timer number
* @return 1 present, 0 not present
*/
int32_t 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 (int32_t)bcr;
}
/**
* @brief Start a timer
* @param no Timer number
* @param mode Timer mode
* @param val Timer limit value (not for RTC)
* @return 0 success, -1 failure
*/
int32_t timer_start(const uint32_t no, const uint32_t mode, const uint32_t val)
{
int32_t ercd = 0;
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:
ercd = -1;
break;
}
return ercd;
}
/**
* @brief Stop timer
*
* @param no Timer number
* @return 0 success, -1 failure
*/
int32_t timer_stop(const uint32_t no)
{
int32_t ercd = 0;
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:
ercd = -1;
break;
}
return ercd;
}
/**
* @brief Get timer current tick
*
* @param no Timer number
* @param val Timer current tick value
* @return 0 success, -1 failure
*/
int32_t timer_current(const uint32_t no, void *val)
{
int32_t ercd = 0;
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:
ercd = -1;
break;
}
return ercd;
}
/**
* @brief Clear the interrupt pending bit of timer
*
* @param no Timer number
* @return 0 success, -1 failure
*/
int32_t timer_int_clear(const uint32_t no)
{
int32_t ercd = 0;
switch (no) {
case TIMER_0:
arc_aux_write(AUX_TIMER0_CTRL,
arc_aux_read(AUX_TIMER0_CTRL) & (~TIMER_CTRL_IP));
break;
case TIMER_1:
arc_aux_write(AUX_TIMER1_CTRL,
arc_aux_read(AUX_TIMER1_CTRL) & (~TIMER_CTRL_IP));
break;
default:
ercd = -1;
break;
}
return ercd;
}
/**
* @brief Initialize internal timer
*/
void arc_timer_init(void)
{
if (timer_present(TIMER_0)) {
timer_stop(TIMER_0);
}
if (timer_present(TIMER_1)) {
timer_stop(TIMER_1);
}
if (timer_present(TIMER_RTC)) {
timer_stop(TIMER_RTC);
}
}
#if defined(ARC_FEATURE_SEC_TIMER1_PRESENT) || defined(ARC_FEATURE_SEC_TIMER0_PRESENT)
/**
* @brief Check whether the specific secure timer present
* @param no Timer number
* @return 1 present, 0 not present
*/
int32_t secure_timer_present(const uint32_t no)
{
uint32_t bcr = arc_aux_read(AUX_BCR_TIMERS);
switch (no) {
case SECURE_TIMER_0:
bcr = (bcr >> 11) & 1;
break;
case SECURE_TIMER_1:
bcr = (bcr >> 12) & 1;
break;
default:
bcr = 0;
/* illegal argument so return false */
break;
}
return (int32_t)bcr;
}
/**
* @brief Start an secure timer
* @param no Timer number
* @param mode Timer mode
* @param val Timer limit value (not for RTC)
* @return 0 success, -1 failure
*/
int32_t secure_timer_start(const uint32_t no, const uint32_t mode, const uint32_t val)
{
int32_t ercd = 0;
switch (no) {
case SECURE_TIMER_0:
arc_aux_write(AUX_SECURE_TIMER0_CTRL, 0);
arc_aux_write(AUX_SECURE_TIMER0_LIMIT, val);
arc_aux_write(AUX_SECURE_TIMER0_CTRL, mode);
arc_aux_write(AUX_SECURE_TIMER0_CNT, 0);
break;
case SECURE_TIMER_1:
arc_aux_write(AUX_SECURE_TIMER1_CTRL, 0);
arc_aux_write(AUX_SECURE_TIMER1_LIMIT, val);
arc_aux_write(AUX_SECURE_TIMER1_CTRL, mode);
arc_aux_write(AUX_SECURE_TIMER1_CNT, 0);
break;
default:
ercd = -1;
break;
}
return ercd;
}
/**
* @brief Stop and clear a secure timer
*
* @param no Timer number
* @return 0 success, -1 failure
*/
int32_t secure_timer_stop(const uint32_t no)
{
int32_t ercd = 0;
switch (no) {
case SECURE_TIMER_0:
arc_aux_write(AUX_SECURE_TIMER0_CTRL, 0);
arc_aux_write(AUX_SECURE_TIMER0_LIMIT, 0);
arc_aux_write(AUX_SECURE_TIMER0_CNT, 0);
break;
case SECURE_TIMER_1:
arc_aux_write(AUX_SECURE_TIMER1_CTRL, 0);
arc_aux_write(AUX_SECURE_TIMER1_LIMIT, 0);
arc_aux_write(AUX_SECURE_TIMER1_CNT, 0);
break;
default:
ercd = -1;
break;
}
return ercd;
}
/**
* @brief Get secure timer current tick
*
* @param no Timer number
* @param val Timer value
* @return 0 success, -1 failure
*/
int32_t secure_timer_current(const uint32_t no, void *val)
{
int32_t ercd = 0;
switch (no) {
case SECURE_TIMER_0:
*((uint32_t *)val) = arc_aux_read(AUX_SECURE_TIMER0_CNT);
break;
case SECURE_TIMER_1:
*((uint32_t *)val) = arc_aux_read(AUX_SECURE_TIMER1_CNT);
break;
default:
ercd = -1;
break;
}
return ercd;
}
/**
* @brief Clear the interrupt pending bit of timer
*
* @param no Timer number
* @return 0 success, -1 failure
*/
int32_t secure_timer_int_clear(const uint32_t no)
{
int32_t ercd = 0;
switch (no) {
case SECURE_TIMER_0:
arc_aux_write(AUX_SECURE_TIMER0_CTRL,
arc_aux_read(AUX_SECURE_TIMER0_CTRL) & (~TIMER_CTRL_IP));
break;
case SECURE_TIMER_1:
arc_aux_write(AUX_SECURE_TIMER1_CTRL,
arc_aux_read(AUX_SECURE_TIMER1_CTRL) & (~TIMER_CTRL_IP));
break;
default:
ercd = -1;
break;
}
return ercd;
}
/**
* @brief Initialize internal secure timer
*/
void secure_timer_init(void)
{
if (secure_timer_present(SECURE_TIMER_0)) {
secure_timer_stop(SECURE_TIMER_0);
}
if (secure_timer_present(SECURE_TIMER_1)) {
secure_timer_stop(SECURE_TIMER_1);
}
}
#endif /* ARC_FEATURE_SEC_TIMER1_PRESENT && ARC_FEATURE_SEC_TIMER0_PRESENT */
/**
* @brief Function for delaying execution for number of microseconds
*
* @param usecs Number of us
*/
void arc_delay_us(uint32_t usecs)
{
if (usecs == 0) {
return;
}
usecs = usecs * gl_loops_per_jiffy / gl_count;
__asm__ __volatile__ (
" .align 4 \n"
" mov %%lp_count, %0 \n"
" lp 1f \n"
" nop \n"
"1: \n"
:
: "r" (usecs)
: "lp_count");
}
/**
* @brief Get calibration values for a given cpu clock source
*
* @param cpu_clock board CPU clock source to calibrate
* @return loops_per_jiffy Calibration value
*/
uint64_t timer_calibrate_delay(uint32_t cpu_clock)
{
uint64_t loopbit;
int32_t lps_precision = LPS_PREC;
volatile uint64_t loops_per_jiffy;
uint32_t timer0_limit;
uint32_t status;
gl_loops_per_jiffy = 1;
gl_count = 1;
cpu_clock /= 1000;
status = cpu_lock_save();
timer0_limit = arc_aux_read(AUX_TIMER0_LIMIT);
arc_aux_write(AUX_TIMER0_LIMIT, 0xFFFFFFFF);
loops_per_jiffy = (1 << 4);
while ((loops_per_jiffy <<= 1) != 0) {
arc_aux_write(AUX_TIMER0_CNT, 0);
arc_delay_us(loops_per_jiffy);
if (arc_aux_read(AUX_TIMER0_CNT) > cpu_clock) {
break;
}
}
loops_per_jiffy >>= 1;
loopbit = loops_per_jiffy;
while (lps_precision-- && (loopbit >>= 1)) {
loops_per_jiffy |= loopbit;
arc_aux_write(AUX_TIMER0_CNT, 0);
arc_delay_us(loops_per_jiffy);
if (arc_aux_read(AUX_TIMER0_CNT) > cpu_clock) {
loops_per_jiffy &= ~loopbit;
}
}
gl_loops_per_jiffy = loops_per_jiffy;
gl_count = 1000;
arc_aux_write(AUX_TIMER0_CNT, 0);
arc_aux_write(AUX_TIMER0_LIMIT, timer0_limit);
cpu_unlock_restore(status);
return loops_per_jiffy;
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,93 +0,0 @@
/* ------------------------------------------
* 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.
*
--------------------------------------------- */
#define __ASSEMBLY__
#include "arc/arc.h"
#include "arc/arc_asm_common.h"
.file "arc_utils.s"
/**
* @brief Go to user mode
*
* @param target Target address to run in user mode, 0 means next
* line of code
* @param sp Stack where the target address runs, 0 means using
* current stack
*/
.text
.global arc_goto_usermode
.align 4
arc_goto_usermode:
cmp r0, 0
mov.z r0, blink
cmp r1, 0
mov.nz sp, r1
#if defined(ARC_FEATURE_SEC_PRESENT)
sr (1 << AUX_ERSEC_STAT_BIT_ERM), [AUX_ERSEC_STAT]
sr sp, [AUX_SEC_U_SP]
#else
sr sp, [AUX_USER_SP]
#endif
lr r1, [AUX_STATUS32]
bset r1, r1, AUX_STATUS_BIT_U
sr r1, [AUX_ERSTATUS]
lr r1, [AUX_STATUS32]
bset r1, r1, AUX_STATUS_BIT_AE
kflag r1
sr r0, [AUX_ERRET]
rtie
/**
* @brief go to kernel mode
* this function uses trap exception to do switch from user mode to kernel mode,
* please install exc_entry_arc_goto_kernelmode for trap exception before call this
* function
* @param target, the target address to run in kernel mode, 0 means next line of code
* @param sp, the stack where the target address runs, 0 means using current stack
*/
.text
.global arc_goto_kernelmode
.global exc_entry_arc_goto_kernelmode
.align 4
arc_goto_kernelmode:
cmp r0, 0
mov.z r0, blink
cmp r1, 0
mov.z r1, sp
trap_s 0
.align 4
exc_entry_arc_goto_kernelmode:
mov sp, r1
sr r0, [AUX_ERRET]
lr r0, [AUX_ERSTATUS]
bclr r0, r0, AUX_STATUS_BIT_U
sr r0, [AUX_ERSTATUS]
rtie

View File

@@ -1,171 +0,0 @@
/*
* 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
*
* 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) 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.
*
--------------------------------------------- */
/**
* @file
* @ingroup ARC_HAL_STARTUP
* @brief C++ support module for ARC
*/
#if defined(__GNU__)
#include "embarc_toolchain.h"
/* embARC's GNU C++ support takes reference from Zephyr (cpp_xxx.c) */
/**
* @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 (*CTOR_FUNC_PTR_T)(void);
/* Constructor function pointer list is generated by the linker script. */
extern CTOR_FUNC_PTR_T __CTOR_LIST__[];
extern CTOR_FUNC_PTR_T __CTOR_END__[];
/**
*
* @brief Invoke all C++ style global object constructors
*
* This routine is invoked before the execution of the
* application's main().
*/
void arc_gnu_do_global_ctors_aux(void)
{
uint32_t num_ctors;
num_ctors = (uint32_t)__CTOR_LIST__[0];
while (num_ctors >= 1) {
__CTOR_LIST__[num_ctors--]();
}
}
typedef void (*DTOR_FUNC_PTR_T)(void);
extern DTOR_FUNC_PTR_T __DTOR_LIST__[];
extern DTOR_FUNC_PTR_T __DTOR_END__[];
/**
*
* @brief Invoke all C++ style global object destructors
*
* This routine is invoked after the execution of the
* application's main().
*/
void arc_gnu_do_global_dtors_aux(void)
{
uint32_t nDtors;
uint32_t i;
nDtors = (uint32_t)__DTOR_LIST__[0];
i = 1;
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
*/
int32_t __cxa_atexit(void (*destructor)(void *), void *objptr, void *dso)
{
return 0;
}
typedef void (*FUNC_PTR_T)(void);
extern FUNC_PTR_T __init_array_start[0];
extern FUNC_PTR_T __init_array_end[0];
/**
* @brief Execute initialization routines referenced in .init_array section
*
* @return N/A
*/
void arc_gnu_do_init_array_aux(void)
{
for (FUNC_PTR_T *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

View File

@@ -1,233 +0,0 @@
/* ------------------------------------------
* 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.
*
--------------------------------------------- */
/**
* @file
* @ingroup ARC_HAL_STARTUP
* @brief Assembly part of startup process
*/
/**
* @addtogroup ARC_HAL_STARTUP
* @{
*/
/** @cond STARTUP_ASM */
#define __ASSEMBLY__
#include "arc/arc.h"
#include "arc/arc_asm_common.h"
.file "arc_startup.s"
.weak _f_sdata /* start of small data, defined in link script */
.weak init_hardware_hook /* app hardware init hook */
.extern board_main
.extern exc_entry_table
/* initial vector table */
.section .init_vector, "a"
.long exc_entry_reset
.section .init_bootstrap, "ax"
.global exc_entry_reset
.global _start
.align 4
_start:
exc_entry_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)
sr exc_entry_table, [AUX_INT_VECT_BASE_S]
#else
sr exc_entry_table, [AUX_INT_VECT_BASE]
#endif
mov gp, _f_sdata /* init small-data base register */
mov fp, 0 /* init fp register */
#if ARC_FEATURE_MP_NUM_CPUS > 1
GET_CORE_ID r0
breq r0, 0, _master_core_startup
_slave_core_wait:
ld r1, [arc_cpu_wake_flag]
brne r0, r1, _slave_core_wait
ld sp, [arc_cpu_sp]
/* signal master core that slave core runs */
st 0, [arc_cpu_wake_flag]
j arc_slave_start
_master_core_startup:
#endif
mov sp, _e_stack /* init stack pointer */
_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 next level initialization */
_arc_reset_call_main:
jl board_main /* board-level main */
b _exit_loop
.global _exit_loop
.global _exit_halt
.align 4
_exit_halt:
_exit_loop:
flag AUX_STATUS_MASK_HALT
nop
nop
nop
b _exit_loop
#if defined(__MW__)
.global arc_mwdt_init, arc_mwdt_fini
.section ".init",text
arc_mwdt_init:
.cfa_bf arc_mwdt_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
arc_mwdt_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 */
/** }@*/

View File

@@ -1,259 +0,0 @@
/* ------------------------------------------
* 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.
*
--------------------------------------------- */
#include "embARC.h"
#include "embARC_debug.h"
#define MAX_SYS_COUNTER_VALUE (0xffffffff)
#ifndef BOARD_SYS_TIMER_HZ
#define BOARD_SYS_TIMER_HZ (1000)
#endif
#ifndef EMBARC_BANNER_TYPE
#define EMBARC_BANNER_TYPE 1
#endif
static const char *embarc_banner =
#if EMBARC_BANNER_TYPE == 1
"----------------------------------------------------------- \r\n\
____ _ ____ \r\n\
| _ \\ _____ _____ _ __ ___ __| | __ ) _ _ \r\n\
| |_) / _ \\ \\ /\\ / / _ \\ '__/ _ \\/ _` | _ \\| | | | \r\n\
| __/ (_) \\ V V / __/ | | __/ (_| | |_) | |_| | \r\n\
|_| \\___/ \\_/\\_/ \\___|_| \\___|\\__,_|____/ \\__, | \r\n\
|___/ \r\n\
_ _ ____ ____ \r\n\
___ _ __ ___ | |__ / \\ | _ \\ / ___| \r\n\
/ _ \\ '_ ` _ \\| '_ \\ / _ \\ | |_) | | \r\n\
| __/ | | | | | |_) / ___ \\| _ <| |___ \r\n\
\\___|_| |_| |_|_.__/_/ \\_\\_| \\_\\\\____| \r\n\
------------------------------------------------------------ \r\n\
";
#else
"-----------------------------------------------------------------------------------------------\r\n\
_/_/_/ _/ _/_/_/ \r\n\
_/ _/ _/_/ _/ _/ _/ _/_/ _/ _/_/ _/_/ _/_/_/ _/ _/ _/ _/ \r\n\
_/_/_/ _/ _/ _/ _/ _/ _/_/_/_/ _/_/ _/_/_/_/ _/ _/ _/_/_/ _/ _/ \r\n\
_/ _/ _/ _/ _/ _/ _/ _/ _/ _/ _/ _/ _/ _/ _/ _/ \r\n\
_/ _/_/ _/ _/ _/_/_/ _/ _/_/_/ _/_/_/ _/_/_/ _/_/_/ \r\n\
_/ \r\n\
_/_/ \r\n\
_/ _/_/ _/_/_/ _/_/_/ \r\n\
_/_/ _/_/_/ _/_/ _/_/_/ _/ _/ _/ _/ _/ \r\n\
_/_/_/_/ _/ _/ _/ _/ _/ _/_/_/_/ _/_/_/ _/ \r\n\
_/ _/ _/ _/ _/ _/ _/ _/ _/ _/ _/ \r\n\
_/_/_/ _/ _/ _/ _/_/_/ _/ _/ _/ _/ _/_/_/ \r\n\
------------------------------------------------------------------------------------------------\r\n\
";
#endif
/** board timer interrupt reset count */
static uint32_t cyc_hz_count = (BOARD_CPU_CLOCK / BOARD_SYS_TIMER_HZ);
/** board timer counter in timer interrupt */
static volatile uint64_t gl_sys_hz_cnt = 0;
/** board 1ms counter */
static volatile uint32_t gl_ms_cnt = 0;
#define HZ_COUNT_CONV(precision, base) ((precision) / (base))
/**
* @brief Board bare-metal timer interrupt.
* Interrupt frequency is based on the defined @ref BOARD_SYS_TIMER_HZ
*/
static void board_timer_isr(void *ptr)
{
timer_int_clear(BOARD_SYS_TIMER_ID);
board_timer_update(BOARD_SYS_TIMER_HZ);
}
/**
* @brief Initialise bare-metal board timer and interrupt
* @details
* This function is called in @ref board_init, and
* it initializes the 1-MS timer interrupt for bare-metal mode
*/
static void board_timer_init(void)
{
if (timer_present(BOARD_SYS_TIMER_ID)) {
int_disable(BOARD_SYS_TIMER_INTNO); /* disable first then enable */
int_handler_install(BOARD_SYS_TIMER_INTNO, board_timer_isr);
timer_start(BOARD_SYS_TIMER_ID, TIMER_CTRL_IE | TIMER_CTRL_NH, cyc_hz_count); /* start 1ms timer interrupt */
int_enable(BOARD_SYS_TIMER_INTNO);
}
}
static void platform_print_banner(void)
{
EMBARC_PRINTF("%s\r\n", embarc_banner);
EMBARC_PRINTF("embARC Build Time: %s, %s\r\n", __DATE__, __TIME__);
#if defined(__GNU__)
EMBARC_PRINTF("Compiler Version: ARC GNU, %s\r\n", __VERSION__);
#else
EMBARC_PRINTF("Compiler Version: Metaware, %s\r\n\r\n", __VERSION__);
#endif
}
EMBARC_WEAK void platform_main(void)
{
#ifdef LIB_CONSOLE
xprintf_setup();
#endif
platform_print_banner();
arc_goto_main(0, NULL);
}
EMBARC_WEAK void board_main(void)
{
#if defined(__MW__)
/* Metaware toolchain C++ init */
arc_mwdt_init();
#elif defined(__GNU__)
/* ARC GNU toolchain C++ init */
arc_gnu_do_global_ctors_aux();
arc_gnu_do_init_array_aux();
#endif
/* init core level interrupt & exception management */
exc_int_init();
/* init cache */
arc_cache_init();
/* necessary board level init */
board_init();
/* Initialise bare-metal board timer and interrupt */
board_timer_init();
/* platform (e.g RTOS, baremetal)level init */
platform_main();
#if defined(__MW__)
arc_mwdt_fini();
#elif defined(__GNU__)
arc_gnu_do_global_dtors_aux();
#endif
}
/**
* @brief Update timer counter and other MS period operation
* in cycling interrupt and must be called periodically.
* @param precision interrupt-period precision in Hz
*/
void board_timer_update(uint32_t precision)
{
static uint32_t sys_hz_update = 0;
static uint32_t sys_ms_update = 0;
uint32_t hz_conv = 0;
/** count sys hz */
hz_conv = HZ_COUNT_CONV(precision, BOARD_SYS_TIMER_HZ);
sys_hz_update++;
if (sys_hz_update >= hz_conv) {
sys_hz_update = 0;
gl_sys_hz_cnt++;
}
/** count ms */
hz_conv = HZ_COUNT_CONV(precision, BOARD_SYS_TIMER_MS_HZ);
sys_ms_update++;
if (sys_ms_update >= hz_conv) {
sys_ms_update = 0;
gl_ms_cnt++;
}
}
/**
* @brief Get current timer's counter value in ticks
* @retval Ticks count in 64 bit format
*/
uint64_t board_get_hwticks(void)
{
uint32_t sub_ticks;
uint64_t total_ticks;
timer_current(TIMER_0, &sub_ticks);
total_ticks = (uint64_t)GET_CUR_MS() * (BOARD_CPU_CLOCK / BOARD_SYS_TIMER_HZ);
total_ticks += (uint64_t)sub_ticks;
return total_ticks;
}
/**
* @brief Get current passed us since timer init
* @retval us Count in 64 bit format
*/
uint64_t board_get_cur_us(void)
{
uint32_t sub_us;
uint64_t total_us;
timer_current(TIMER_0, &sub_us);
sub_us = ((uint64_t)sub_us * 1000000) / BOARD_CPU_CLOCK;
total_us = ((uint64_t)GET_CUR_MS()) * 1000 + (uint64_t)sub_us;
return total_us;
}
/**
* @brief Get current passed ms since timer init
* @retval ms Count in 32 bit format
*/
uint32_t board_get_cur_ms(void)
{
return gl_ms_cnt;
}
/**
* @brief Get board timer counter in timer interrupt
* @retval Count in 64 bit format
*/
uint64_t board_get_cur_syshz(void)
{
return gl_sys_hz_cnt;
}
/**
* @brief Function for delaying execution for number of milliseconds
* @details
* This function needs a 1-MS timer interrupt to work.
* For bare-metal, it is implemented in this file.
* @param ms Delay in milliseconds
*/
void board_delay_ms(uint32_t ms)
{
uint64_t start_us, us_delayed;
us_delayed = ((uint64_t)ms * 1000);
start_us = board_get_cur_us();
while ((board_get_cur_us() - start_us) < us_delayed) {
;
}
}

View File

@@ -1,106 +0,0 @@
/* ------------------------------------------
* 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.
*
--------------------------------------------- */
/**
*
* @file
* @ingroup BOARD_COMMON
* @brief Common board definitions used with all boards
* @details
* - This header file will contain board related settings for different boards.
* - Each board configurations are put in its own header file, like emsk/emsk.h
* - If you want to change the configuration, you need to go to related header file, e.g.
* if you want to change EMSK board settings, you need to go to emsk/emsk.h
*/
/**
* @addtogroup BOARD_COMMON
* @{
*/
#ifndef H_BOARD
#define H_BOARD
/**
* @todo add comments and documents to describe the macros
* @note the following macros must use the same name, because
* they are used by middleware and other applications
*/
/** here is a sample of EMSK board resource definitions */
#ifdef BOARD_EMSK
#include "emsk/emsk.h"
#endif /* BOARD_EMSK */
/** you can add your board configuration as BOARD_EMSK defined up */
/** nsim related definition */
#ifdef BOARD_NSIM
#include "nsim.h"
#endif /* BOARD_NSIM */
#ifdef BOARD_AXS
#include "axs/axs.h"
#endif /* BOARD_AXS */
#ifdef BOARD_HSDK
#include "hsdk/hsdk.h"
#endif /* BOARD_HSDK */
#ifdef BOARD_IOTDK
#include "iotdk/iotdk.h"
#endif /* BOARD_IOTDK */
#ifdef BOARD_EMSDP
#include "emsdp/emsdp.h"
#endif /* BOARD_EMDK */
#ifdef __cplusplus
extern "C" {
#endif
extern void board_init(void);
extern void board_timer_update(uint32_t precision);
extern void board_delay_ms(uint32_t ms);
extern uint64_t board_get_hwticks(void);
extern uint64_t board_get_cur_us(void);
extern uint64_t board_get_cur_syshz(void);
extern uint32_t board_get_cur_ms(void);
extern void platform_main(void);
extern void board_main(void);
#ifdef __cplusplus
}
#endif
#define GET_CUR_SYSHZ() bord_get_cur_syshz()
#define GET_CUR_MS() board_get_cur_ms()
#define GET_CUR_US() board_get_cur_us()
#define GET_CUR_HWTICKS() board_get_hwticks()
#endif /* H_BOARD */
/** @} end of group BOARD_COMMON */

View File

@@ -1,539 +0,0 @@
/* ------------------------------------------
* 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.
*
--------------------------------------------- */
#include "embARC_toolchain.h"
#include "embARC_error.h"
#include "arc/arc_exception.h"
#include "device/designware/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.
* @{
*/
/**
* @fn uint32_t dw_gpio_read_ext(DW_GPIO_PORT_PTR port)
*/
Inline uint32_t dw_gpio_read_ext(DW_GPIO_PORT_PTR port)
{
return port->regs->EXT_PORTS[port->no];
}
/**
* @fn uint32_t dw_gpio_read_dir(DW_GPIO_PORT_PTR port)
*/
Inline uint32_t dw_gpio_read_dir(DW_GPIO_PORT_PTR port)
{
return port->regs->SWPORTS[port->no].DDR;
}
/**
* @fn uint32_t dw_gpio_read_dr(DW_GPIO_PORT_PTR port)
*/
Inline uint32_t dw_gpio_read_dr(DW_GPIO_PORT_PTR port)
{
return port->regs->SWPORTS[port->no].DR;
}
/**
* @fn uint32_t dw_gpio_read_mthd(DW_GPIO_PORT_PTR port)
*/
Inline uint32_t dw_gpio_read_mthd(DW_GPIO_PORT_PTR port)
{
return port->regs->INTEN;
}
/**
* @fn void dw_gpio_int_enable(DW_GPIO_PORT_PTR port, uint32_t bit_mask)
*/
Inline void dw_gpio_int_enable(DW_GPIO_PORT_PTR port, uint32_t bit_mask)
{
port->regs->INTEN |= bit_mask;
}
/**
* @fn void dw_gpio_int_disable(DW_GPIO_PORT_PTR port, uint32_t bit_mask)
*/
Inline void dw_gpio_int_disable(DW_GPIO_PORT_PTR port, uint32_t bit_mask)
{
port->regs->INTEN &= (~bit_mask);
}
/**
* @fn void dw_gpio_int_mask(DW_GPIO_PORT_PTR port, uint32_t bit_mask)
*/
Inline void dw_gpio_int_mask(DW_GPIO_PORT_PTR port, uint32_t bit_mask)
{
port->regs->INTMASK |= bit_mask;
}
/**
* @fn void dw_gpio_int_unmask(DW_GPIO_PORT_PTR port, uint32_t bit_mask)
*/
Inline void dw_gpio_int_unmask(DW_GPIO_PORT_PTR port, uint32_t bit_mask)
{
port->regs->INTMASK &= (~bit_mask);
}
/**
* @fn uint32_t dw_gpio_int_read_level(DW_GPIO_PORT_PTR port)
*/
Inline uint32_t dw_gpio_int_read_level(DW_GPIO_PORT_PTR port)
{
return port->regs->INTTYPE_LEVEL;
}
/**
* @fn uint32_t dw_gpio_int_read_polarity(DW_GPIO_PORT_PTR port)
*/
Inline uint32_t dw_gpio_int_read_polarity(DW_GPIO_PORT_PTR port)
{
return port->regs->INT_POLARITY;
}
/**
* @fn uint32_t dw_gpio_int_read_debounce(DW_GPIO_PORT_PTR port)
*/
Inline uint32_t dw_gpio_int_read_debounce(DW_GPIO_PORT_PTR port)
{
return port->regs->DEBOUNCE;
}
/**
* @fn uint32_t dw_gpio_int_read_status(DW_GPIO_PORT_PTR port)
*/
Inline uint32_t dw_gpio_int_read_status(DW_GPIO_PORT_PTR port)
{
return port->regs->INTSTATUS;
}
/**
* @fn void dw_gpio_int_clear(DW_GPIO_PORT_PTR port, uint32_t bit_mask)
*/
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_toggle_dr(DW_GPIO_PORT_PTR port, uint32_t bit_mask)
{
uint32_t temp_reg1, temp_reg2;
temp_reg1 = port->regs->SWPORTS[port->no].DR;
// save unmasked bits value
temp_reg2 = temp_reg1 & (~bit_mask);
// toggle masked bits value
temp_reg1 = (~temp_reg1) & bit_mask;
// combine both masked and unmasked bits
temp_reg1 |= temp_reg2;
port->regs->SWPORTS[port->no].DR = temp_reg1;
}
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 */
if (port->intno != DW_GPIO_INVALID_INTNO) { // Handle Bit ISR 1-1 map to vector table
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;
port_info_ptr->bitofs = 0;
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--;
port_info_ptr->bitofs = 0;
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);
if (port->intno != DW_GPIO_INVALID_INTNO) {
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 if (ctrl_cmd == GPIO_CMD_TOGGLE_BITS) {
val32 = (uint32_t)param;
// Only mask the output bits
val32 &= port_info_ptr->direction;
dw_gpio_toggle_dr(port, val32);
} 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) {
if (port->intno != DW_GPIO_INVALID_INTNO) {
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) {
if (port->intno != DW_GPIO_INVALID_INTNO) {
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 {
/* this code cannot never be reached */
/* coverity[dead_error_line] */
dw_gpio_int_clear(port, gpio_bit_isr_state);
}
for (i = 0; i < max_int_bit_count; i++) {
if (gpio_bit_isr_state & (1 << i)) {
/* this bit interrupt enabled */
port_info_ptr->bitofs = i;
if (port->gpio_bit_isr->int_bit_handler_ptr[i]) {
port->gpio_bit_isr->int_bit_handler_ptr[i](gpio_obj);
}
dw_gpio_int_clear(port, (1 << i)); /** clear this bit interrupt */
}
}
error_exit:
return ercd;
}

View File

@@ -1,400 +0,0 @@
/* ------------------------------------------
* Copyright (c) 2018, 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.
*
--------------------------------------------- */
#include "embARC_toolchain.h"
#include "embARC_error.h"
#include "arc/arc_exception.h"
#include "device/designware/dw_pwm_timer.h"
/** check expressions used in DesignWare PWM_TIMER driver implementation */
#define DW_PWM_TIMER_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_PWM_TIMER_INFO_OBJECT(pwm_timerinfo_obj_ptr) { \
DW_PWM_TIMER_CHECK_EXP((pwm_timerinfo_obj_ptr) != NULL, E_OBJ); \
DW_PWM_TIMER_CHECK_EXP(((pwm_timerinfo_obj_ptr)->pwm_timer_ctrl) != NULL, E_OBJ); \
}
#endif
/**
* @fn uint32_t dw_pwm_timer_int_read_status(DW_PWM_TIMER_CTRL_PTR port)
*/
Inline uint32_t dw_pwm_timer_int_read_status(DW_PWM_TIMER_CTRL_PTR port)
{
return port->regs->PWM_TIMERS_INT_STATUS;
}
/**
* @fn void dw_pwm_timer_timer_enable(DW_PWM_TIMER_CTRL_PTR port, uint32_t ch)
*/
Inline void dw_pwm_timer_timer_enable(DW_PWM_TIMER_CTRL_PTR port, uint32_t ch)
{
port->regs->CTRL[ch].CONTROL_REG |= 0x03;
}
/**
* @fn void dw_pwm_timer_timer_disable(DW_PWM_TIMER_CTRL_PTR port, uint32_t ch)
*/
Inline void dw_pwm_timer_timer_disable(DW_PWM_TIMER_CTRL_PTR port, uint32_t ch)
{
port->regs->CTRL[ch].CONTROL_REG &= (~0x03);
}
/**
* @fn void dw_pwm_timer_pwm_enable(DW_PWM_TIMER_CTRL_PTR port, uint32_t ch)
*/
Inline void dw_pwm_timer_pwm_enable(DW_PWM_TIMER_CTRL_PTR port, uint32_t ch)
{
port->regs->CTRL[ch].CONTROL_REG |= 0x08;
}
/**
* @fn void dw_pwm_timer_pwm_disable(DW_PWM_TIMER_CTRL_PTR port, uint32_t ch)
*/
Inline void dw_pwm_timer_pwm_disable(DW_PWM_TIMER_CTRL_PTR port, uint32_t ch)
{
port->regs->CTRL[ch].CONTROL_REG &= (~0x08);
}
/**
* @fn void dw_pwm_timer_count_set(DW_PWM_TIMER_CTRL_PTR port, uint8_t ch, uint16_t val)
*/
Inline void dw_pwm_timer_count_set(DW_PWM_TIMER_CTRL_PTR port, uint8_t ch, uint16_t val)
{
port->regs->CTRL[ch].LOAD_COUNT = val;
}
/**
* @fn uint16_t dw_pwm_timer_count_get(DW_PWM_TIMER_CTRL_PTR port, uint8_t ch)
*/
Inline uint16_t dw_pwm_timer_count_get(DW_PWM_TIMER_CTRL_PTR port, uint8_t ch)
{
return port->regs->CTRL[ch].LOAD_COUNT;
}
/**
* @fn void dw_pwm_timer_count2_set(DW_PWM_TIMER_CTRL_PTR port, uint8_t ch, uint16_t val)
*/
Inline void dw_pwm_timer_count2_set(DW_PWM_TIMER_CTRL_PTR port, uint8_t ch, uint16_t val)
{
port->regs->LOAD_COUNT2[ch] = val;
}
/**
* @fn uint16_t dw_pwm_timer_count2_get(DW_PWM_TIMER_CTRL_PTR port, uint8_t ch)
*/
Inline uint16_t dw_pwm_timer_count2_get(DW_PWM_TIMER_CTRL_PTR port, uint8_t ch)
{
return port->regs->LOAD_COUNT2[ch];
}
static void dw_pwm_timer_int_clear_all(DW_PWM_TIMER_CTRL_PTR port)
{
int32_t reg_val;
reg_val = port->regs->PWM_TIMERS_EOI;
}
static void dw_pwm_timer_int_clear(DW_PWM_TIMER_CTRL_PTR port, uint32_t ch)
{
int32_t reg_val;
reg_val = port->regs->CTRL[ch].EOI;
}
/* interface for DEV_PWM_TIMER */
/** Open designware pwm_timer device */
int32_t dw_pwm_timer_open(DEV_PWM_TIMER *pwm_timer_obj)
{
int32_t ercd = E_OK;
DEV_PWM_TIMER_INFO_PTR port_info_ptr = &(pwm_timer_obj->pwm_timer_info);
/* START ERROR CHECK */
VALID_CHK_PWM_TIMER_INFO_OBJECT(port_info_ptr);
/* END OF ERROR CHECK */
DW_PWM_TIMER_CTRL_PTR port = (DW_PWM_TIMER_CTRL_PTR)(port_info_ptr->pwm_timer_ctrl);
port_info_ptr->opn_cnt++;
if (port_info_ptr->opn_cnt > 1) { /* opened before */
return E_OPNED;
}
if (port->intno != DW_PWM_TIMER_INVALID_INTNO) {
for (uint8_t i = 0; i < port->ch_num; i++) {
dw_pwm_timer_timer_disable(port, i);
dw_pwm_timer_pwm_disable(port, i);
int_disable(port->intno + i);
int_handler_install(port->intno + i, port->int_handler);
}
}
error_exit:
return ercd;
}
/** Close designware pwm_timer device */
int32_t dw_pwm_timer_close(DEV_PWM_TIMER *pwm_timer_obj)
{
int32_t ercd = E_OK;
DEV_PWM_TIMER_INFO_PTR port_info_ptr = &(pwm_timer_obj->pwm_timer_info);
/* START ERROR CHECK */
VALID_CHK_PWM_TIMER_INFO_OBJECT(port_info_ptr);
/* END OF ERROR CHECK */
DW_PWM_TIMER_CTRL_PTR port = (DW_PWM_TIMER_CTRL_PTR)(port_info_ptr->pwm_timer_ctrl);
DW_PWM_TIMER_CHECK_EXP(port_info_ptr->opn_cnt > 0, E_OK);
port_info_ptr->opn_cnt--;
if (port_info_ptr->opn_cnt == 0) {
if (port->intno != DW_PWM_TIMER_INVALID_INTNO) {
for (uint8_t i = 0; i < port->ch_num; i++) {
dw_pwm_timer_timer_disable(port, i);
dw_pwm_timer_pwm_disable(port, i);
int_disable(port->intno + i);
}
}
} else {
ercd = E_OPNED;
}
error_exit:
return ercd;
}
/** Read designware pwm_timer device value */
int32_t dw_pwm_timer_read(DEV_PWM_TIMER *pwm_timer_obj, uint32_t ch, uint32_t *mode, uint32_t *freq, uint32_t *dc)
{
int32_t ercd = E_OK;
DEV_PWM_TIMER_INFO_PTR port_info_ptr = &(pwm_timer_obj->pwm_timer_info);
/* START ERROR CHECK */
VALID_CHK_PWM_TIMER_INFO_OBJECT(port_info_ptr);
/* END OF ERROR CHECK */
DW_PWM_TIMER_CTRL_PTR port = (DW_PWM_TIMER_CTRL_PTR)(port_info_ptr->pwm_timer_ctrl);
DW_PWM_TIMER_CHECK_EXP(port_info_ptr->opn_cnt > 0, E_CLSED);
DW_PWM_TIMER_CHECK_EXP((ch >= 0) && (ch < port->ch_num), E_PAR);
int32_t count_low = dw_pwm_timer_count_get(port, ch);
int32_t count_high = dw_pwm_timer_count2_get(port, ch);
*mode = port->mode[ch];
if (*mode == DEV_PWM_TIMER_MODE_TIMER) {
*dc = 100;
if (count_low != 0) {
*freq = port->clock / (count_low * 2);
} else {
*freq = 0;
}
} else if (*mode == DEV_PWM_TIMER_MODE_PWM) {
if (count_low == 0 && count_high == 0) {
*dc = 0;
*freq = 0;
} else {
*dc = (count_high * 100) / (count_high + count_low);
*freq = port->clock / (count_high + count_low);
}
} else {
*dc = 0;
*freq = 0;
}
error_exit:
return ercd;
}
/** Write designware pwm_timer device value */
int32_t dw_pwm_timer_write(DEV_PWM_TIMER *pwm_timer_obj, uint32_t ch, uint32_t mode, uint32_t freq, uint32_t dc)
{
int32_t ercd = E_OK;
int32_t count, count_high;
DEV_PWM_TIMER_INFO_PTR port_info_ptr = &(pwm_timer_obj->pwm_timer_info);
/* START ERROR CHECK */
VALID_CHK_PWM_TIMER_INFO_OBJECT(port_info_ptr);
/* END OF ERROR CHECK */
DW_PWM_TIMER_CTRL_PTR port = (DW_PWM_TIMER_CTRL_PTR)(port_info_ptr->pwm_timer_ctrl);
DW_PWM_TIMER_CHECK_EXP(port_info_ptr->opn_cnt > 0, E_CLSED);
DW_PWM_TIMER_CHECK_EXP((ch >= 0) && (ch < port->ch_num), E_PAR);
DW_PWM_TIMER_CHECK_EXP((dc >= 0) && (dc <= 100), E_PAR);
if (mode == DEV_PWM_TIMER_MODE_TIMER) {
DW_PWM_TIMER_CHECK_EXP(freq > 0, E_PAR);
port->mode[ch] = mode;
count = port->clock / freq;
dw_pwm_timer_count_set(port, ch, count / 2);
dw_pwm_timer_count2_set(port, ch, 0);
dw_pwm_timer_timer_enable(port, ch);
dw_pwm_timer_pwm_disable(port, ch);
int_enable(port->intno + ch);
} else if (mode == DEV_PWM_TIMER_MODE_PWM) {
DW_PWM_TIMER_CHECK_EXP(freq > 0, E_PAR);
port->mode[ch] = mode;
count = port->clock / freq;
count_high = (count * dc) / 100;
dw_pwm_timer_count_set(port, ch, count - count_high);
dw_pwm_timer_count2_set(port, ch, count_high);
dw_pwm_timer_timer_enable(port, ch);
dw_pwm_timer_pwm_enable(port, ch);
int_disable(port->intno + ch);
} else if (mode == DEV_PWM_TIMER_MODE_CLOSE) {
port->mode[ch] = mode;
dw_pwm_timer_count_set(port, ch, 0);
dw_pwm_timer_count2_set(port, ch, 0);
dw_pwm_timer_timer_disable(port, ch);
dw_pwm_timer_pwm_disable(port, ch);
int_disable(port->intno + ch);
}
error_exit:
return ercd;
}
/** Control designware pwm_timer device */
int32_t dw_pwm_timer_control(DEV_PWM_TIMER *pwm_timer_obj, uint32_t ch, uint32_t ctrl_cmd, void *par)
{
int32_t ercd = E_OK;
DEV_PWM_TIMER_INFO_PTR port_info_ptr = &(pwm_timer_obj->pwm_timer_info);
/* START ERROR CHECK */
VALID_CHK_PWM_TIMER_INFO_OBJECT(port_info_ptr);
/* END OF ERROR CHECK */
DW_PWM_TIMER_CTRL_PTR port = (DW_PWM_TIMER_CTRL_PTR)(port_info_ptr->pwm_timer_ctrl);
DW_PWM_TIMER_CHECK_EXP(port_info_ptr->opn_cnt > 0, E_CLSED);
DW_PWM_TIMER_CHECK_EXP((ch >= 0) && (ch < port->ch_num), E_PAR);
DEV_PWM_TIMER_CFG *cfg_ptr;
switch (ctrl_cmd) {
case PWM_TIMER_CMD_SET_CFG:
cfg_ptr = (DEV_PWM_TIMER_CFG *) par;
dw_pwm_timer_count_set(port, ch, cfg_ptr->count_low);
dw_pwm_timer_count2_set(port, ch, cfg_ptr->count_high);
if (cfg_ptr->isr_hander != NULL) {
port->ch_isr->int_ch_handler_ptr[ch] = cfg_ptr->isr_hander;
}
if (cfg_ptr->mode == DEV_PWM_TIMER_MODE_TIMER) {
port->mode[ch] = cfg_ptr->mode;
dw_pwm_timer_timer_enable(port, ch);
int_enable(port->intno + ch);
} else if (cfg_ptr->mode == DEV_PWM_TIMER_MODE_PWM) {
port->mode[ch] = cfg_ptr->mode;
dw_pwm_timer_timer_enable(port, ch);
dw_pwm_timer_pwm_enable(port, ch);
} else if (cfg_ptr->mode == DEV_PWM_TIMER_MODE_CLOSE) {
port->mode[ch] = cfg_ptr->mode;
dw_pwm_timer_timer_disable(port, ch);
dw_pwm_timer_pwm_disable(port, ch);
}
break;
case PWM_TIMER_CMD_GET_CFG:
cfg_ptr = (DEV_PWM_TIMER_CFG *) par;
cfg_ptr->count_low = dw_pwm_timer_count_get(port, ch);
cfg_ptr->count_high = dw_pwm_timer_count2_get(port, ch);
if (cfg_ptr->isr_hander != NULL) {
cfg_ptr->isr_hander = port->ch_isr->int_ch_handler_ptr[ch];
}
cfg_ptr->mode = port->mode[ch];
break;
case PWM_TIMER_CMD_DIS_CH:
dw_pwm_timer_timer_disable(port, ch);
break;
case PWM_TIMER_CMD_ENA_CH:
dw_pwm_timer_timer_enable(port, ch);
break;
case PWM_TIMER_CMD_DIS_ISR:
int_disable(port->intno + ch);
break;
case PWM_TIMER_CMD_ENA_ISR:
int_enable(port->intno + ch);
break;
case PWM_TIMER_CMD_SET_ISR:
DW_PWM_TIMER_CHECK_EXP((par != NULL) && CHECK_ALIGN_4BYTES(par), E_PAR);
port->ch_isr->int_ch_handler_ptr[ch] = (DEV_PWM_TIMER_HANDLER)par;
break;
case PWM_TIMER_CMD_GET_ISR:
DW_PWM_TIMER_CHECK_EXP((par != NULL) && CHECK_ALIGN_4BYTES(par), E_PAR);
par = (void *)(port->ch_isr->int_ch_handler_ptr[ch]);
break;
default:
ercd = E_NOSPT;
break;
}
error_exit:
return ercd;
}
/** designware pwm_timer interrupt process */
int32_t dw_pwm_timer_isr_handler(DEV_PWM_TIMER *pwm_timer_obj, void *ptr)
{
int32_t ercd = E_OK;
DEV_PWM_TIMER_INFO_PTR port_info_ptr = &(pwm_timer_obj->pwm_timer_info);
/* START ERROR CHECK */
VALID_CHK_PWM_TIMER_INFO_OBJECT(port_info_ptr);
/* END OF ERROR CHECK */
DW_PWM_TIMER_CTRL_PTR port = (DW_PWM_TIMER_CTRL_PTR)(port_info_ptr->pwm_timer_ctrl);
uint32_t i, pwm_timer_bit_isr_state;
uint32_t max_int_bit_count = 0;
/** read interrupt status */
pwm_timer_bit_isr_state = dw_pwm_timer_int_read_status(port);
if (port->ch_isr) {
max_int_bit_count = (port->ch_isr->int_ch_max_cnt);
} else {
dw_pwm_timer_int_clear_all(port);
}
for (i = 0; i < max_int_bit_count; i++) {
if (pwm_timer_bit_isr_state & (1 << i)) {
/* this bit interrupt enabled */
if (port->ch_isr->int_ch_handler_ptr[i]) {
port->ch_isr->int_ch_handler_ptr[i](pwm_timer_obj);
}
dw_pwm_timer_int_clear(port, i); /** clear this bit interrupt */
}
}
error_exit:
return ercd;
}

View File

@@ -1,594 +0,0 @@
/* ------------------------------------------
* 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.
*
--------------------------------------------- */
#include "embARC_toolchain.h"
#include "embARC_error.h"
#include "arc/arc_exception.h"
#include "board.h"
#include "device/designware/dw_sdio_hal.h"
#include "device/designware/dw_sdio.h"
#include "embARC_debug.h"
#define min(a, b) (((a) < (b)) ? (a) : (b))
/**
* @fn void dw_sdio_enable_card_threshold(DW_SDIO_CTRL_PTR sdio, uint32_t threshold)
*/
Inline void dw_sdio_enable_card_threshold(DW_SDIO_CTRL_PTR sdio, uint32_t threshold)
{
/* according to datasheet, write threshold is only applicable for HS400 mode */
uint32_t reg;
reg = dw_sdio_reg_read(sdio, DWSDIO_REG_CARD_THR_CTRL);
reg |= 0x1;
dw_sdio_reg_write(sdio, DWSDIO_REG_CARD_THR_CTRL, reg);
}
/**
* @fn void dw_sdio_block_size_set(DW_SDIO_CTRL_PTR sdio, uint32_t bytes, uint32_t blksz)
*/
Inline void dw_sdio_block_size_set(DW_SDIO_CTRL_PTR sdio, uint32_t bytes, uint32_t blksz)
{
dw_sdio_reg_write(sdio, DWSDIO_REG_BYTCNT, bytes);
dw_sdio_reg_write(sdio, DWSDIO_REG_BLKSIZ, blksz);
}
/**
* @fn void dw_sdio_fifo_read_poll(DW_SDIO_CTRL_PTR sdio, uint32_t *buf, uint32_t size)
*/
Inline void dw_sdio_fifo_read_poll(DW_SDIO_CTRL_PTR sdio, uint32_t *buf, uint32_t size)
{
uint32_t len;
uint32_t i;
while (size) {
do {
len = dw_sdio_reg_read(sdio, DWSDIO_REG_STATUS);
} while (len & DWSDIO_STATUS_FIFO_EMPTY);
len = (len & DWSDIO_STATUS_MASK_FIFO) >> DWSDIO_STATUS_BIT_FIFO;
len = min(size, len);
for (i = 0; i < len; i++) {
*buf++ = dw_sdio_reg_read(sdio, DWSDIO_REG_DATA);
}
size = size > len ? (size - len) : 0;
}
}
/**
* @fn void dw_sdio_clk_enable(DW_SDIO_CTRL_PTR sdio, uint32_t card_number)
*/
Inline void dw_sdio_clk_enable(DW_SDIO_CTRL_PTR sdio, uint32_t card_number)
{
uint32_t reg;
reg = dw_sdio_reg_read(sdio, DWSDIO_REG_CLKENA);
reg |= (1 << card_number);
dw_sdio_reg_write(sdio, DWSDIO_REG_CLKENA, reg);
}
/**
* @fn dw_sdio_clk_disable(DW_SDIO_CTRL_PTR sdio, uint32_t card_number)
*/
Inline void dw_sdio_clk_disable(DW_SDIO_CTRL_PTR sdio, uint32_t card_number)
{
uint32_t reg;
reg = dw_sdio_reg_read(sdio, DWSDIO_REG_CLKENA);
reg &= ~(1 << card_number);
dw_sdio_reg_write(sdio, DWSDIO_REG_CLKENA, reg);
}
/**
* @fn void dw_sdio_fifo_write_poll(DW_SDIO_CTRL_PTR sdio, uint32_t *buf, uint32_t size)
*/
Inline void dw_sdio_fifo_write_poll(DW_SDIO_CTRL_PTR sdio, uint32_t *buf, uint32_t size)
{
uint32_t len;
uint32_t i;
uint32_t fifo_depth = sdio->fifo_depth;
while (size) {
do {
len = dw_sdio_reg_read(sdio, DWSDIO_REG_STATUS);
} while (len & DWSDIO_STATUS_FIFO_FULL);
len = fifo_depth - ((len & DWSDIO_STATUS_MASK_FIFO) >> DWSDIO_STATUS_BIT_FIFO);
len = min(size, len);
for (i = 0; i < len; i++) {
dw_sdio_reg_write(sdio, DWSDIO_REG_DATA, *buf++);
}
size = size > len ? (size - len) : 0;
}
}
/**
* @fn void dw_sdio_power_on(DW_SDIO_CTRL_PTR sdio, uint32_t card_number)
*/
Inline void dw_sdio_power_on(DW_SDIO_CTRL_PTR sdio, uint32_t card_number)
{
dw_sdio_reg_write(sdio, DWSDIO_REG_PWREN, (1 << card_number));
}
/**
* @fn void dw_sdio_power_off(DW_SDIO_CTRL_PTR sdio, uint32_t card_number)
*/
Inline void dw_sdio_power_off(DW_SDIO_CTRL_PTR sdio, uint32_t card_number)
{
uint32_t reg = dw_sdio_reg_read(sdio, DWSDIO_REG_PWREN);
reg &= ~(1 << card_number);
dw_sdio_reg_write(sdio, DWSDIO_REG_PWREN, reg);
}
/**
* @fn void dw_sdio_reset(DW_SDIO_CTRL_PTR sdio, uint32_t card_number)
*/
Inline void dw_sdio_reset(DW_SDIO_CTRL_PTR sdio, uint32_t card_number)
{
uint32_t reg;
reg = dw_sdio_reg_read(sdio, DWSDIO_REG_RST_N);
reg &= ~(1 << card_number);
dw_sdio_reg_write(sdio, DWSDIO_REG_RST_N, reg);
reg |= (1 << card_number);
dw_sdio_reg_write(sdio, DWSDIO_REG_RST_N, reg);
}
/**
* @fn void dw_sdio_bus_type_set(DW_SDIO_CTRL_PTR sdio, uint32_t card_number, uint32_t width)
*/
Inline void dw_sdio_bus_type_set(DW_SDIO_CTRL_PTR sdio, uint32_t card_number, uint32_t width)
{
uint32_t reg;
reg = dw_sdio_reg_read(sdio, DWSDIO_REG_CTYPE);
reg &= ~((1 << card_number) | (1 << (card_number + 16)));
switch (width) {
case 1: break;
case 4: reg |= (1 << card_number); break;
case 8: reg |= (1 << (card_number + 16)); break;
default: break;
}
dw_sdio_reg_write(sdio, DWSDIO_REG_CTYPE, reg);
}
/**
* @fn void dw_sdio_ref_clk_set(DW_SDIO_CTRL_PTR sdio, uint32_t ref_clk)
*/
Inline void dw_sdio_ref_clk_set(DW_SDIO_CTRL_PTR sdio, uint32_t ref_clk)
{
/* 0: 25 Mhz, 1: 50 Mhz, 2: 100 Mhz */
uint32_t reg;
if (ref_clk == 50000000) {
ref_clk = 1;
} else if (ref_clk == 100000000) {
ref_clk = 2;
} else {
ref_clk = 0;
}
reg = dw_sdio_reg_read(sdio, DWSDIO_REG_UHS_REG_EXT);
reg &= ~(DWSDIO_UHS_REG_EXT_MASK_REFCLK);
reg |= (ref_clk << DWSDIO_UHS_REG_EXT_BIT_REFCLK);
dw_sdio_reg_write(sdio, DWSDIO_REG_UHS_REG_EXT, reg);
}
static int32_t dw_sdio_bus_freq_set(DW_SDIO_CTRL_PTR sdio, uint32_t card_number, uint32_t freq)
{
uint32_t clk;
uint32_t div;
uint32_t status;
int32_t timeout = 10000;
clk = sdio->ref_clk;
if (freq == clk) {
div = 0;
} else {
div = DIV_ROUND_UP(clk, 2 * freq);
}
dw_sdio_clk_disable(sdio, card_number);
dw_sdio_reg_write(sdio, DWSDIO_REG_CLKSRC, 0);
dw_sdio_reg_write(sdio, DWSDIO_REG_CLKDIV, div);
dw_sdio_reg_write(sdio, DWSDIO_REG_CMD, DWSDIO_CMD_PRV_DAT_WAIT |
DWSDIO_CMD_UPD_CLK | DWSDIO_CMD_START | DWSDIO_CMD_USE_HOLD_REG);
do {
status = dw_sdio_reg_read(sdio, DWSDIO_REG_CMD);
if (timeout-- < 0) {
DBG("%s: Timeout!\n", __func__);
return E_TMOUT;
}
} while (status & DWSDIO_CMD_START);
dw_sdio_clk_enable(sdio, card_number);
dw_sdio_reg_write(sdio, DWSDIO_REG_CMD, DWSDIO_CMD_PRV_DAT_WAIT |
DWSDIO_CMD_UPD_CLK | DWSDIO_CMD_START | DWSDIO_CMD_USE_HOLD_REG);
timeout = 10000;
do {
status = dw_sdio_reg_read(sdio, DWSDIO_REG_CMD);
if (timeout-- < 0) {
DBG("%s: Timeout!\n", __func__);
return E_TMOUT;
}
} while (status & DWSDIO_CMD_START);
return E_OK;
}
static int32_t dw_sdio_reset_wait(DW_SDIO_CTRL_PTR sdio, uint32_t reset_val)
{
uint32_t try = 1000;
uint32_t ctrl;
dw_sdio_reg_write(sdio, DWSDIO_REG_CTRL, reset_val);
while (try--) {
ctrl = dw_sdio_reg_read(sdio, DWSDIO_REG_CTRL);
if (!(ctrl & DWSDIO_CTRL_RESET_ALL)) {
return E_SYS;
}
}
return E_OK;
}
static int32_t dw_sdio_cmd_set(DW_SDIO_CTRL_PTR sdio, SDIO_CMD_PTR cmd, SDIO_DATA_PTR data)
{
uint32_t reg = 0;
dw_sdio_reg_write(sdio, DWSDIO_REG_CMDARG, cmd->arg);
if (data) {
reg |= DWSDIO_CMD_DATA_EXP;
if (data->flags & SDIO_DATA_WRITE) {
reg |= DWSDIO_CMD_RW;
}
}
if ((cmd->resp_type & SDIO_RSP_136) && (cmd->resp_type & SDIO_RSP_BUSY)) {
return -1;
}
/* to fix */
if (cmd->cmdidx == 12) {
reg |= DWSDIO_CMD_ABORT_STOP;
} else {
reg |= DWSDIO_CMD_PRV_DAT_WAIT;
}
if (cmd->resp_type & SDIO_RSP_PRESENT) {
reg |= DWSDIO_CMD_RESP_EXP;
if (cmd->resp_type & SDIO_RSP_136) {
reg |= DWSDIO_CMD_RESP_LENGTH;
}
}
if (cmd->resp_type & SDIO_RSP_CRC) {
reg |= DWSDIO_CMD_CHECK_CRC;
}
reg |= (cmd->cmdidx | (cmd->card << DWSDIO_CMD_BIT_CARD_NO) | DWSDIO_CMD_START
| DWSDIO_CMD_USE_HOLD_REG);
DBG("Sending CMD%d to card %d \r\n", cmd->cmdidx, cmd->card);
dw_sdio_reg_write(sdio, DWSDIO_REG_CMD, reg);
return 0;
}
static int32_t dw_sdio_data_transfer_poll(DW_SDIO_CTRL_PTR sdio, SDIO_DATA_PTR data)
{
uint32_t size;
uint32_t status;
uint32_t timeout = 1000;
uint32_t start = GET_CUR_MS();
size = data->blksz * data->blkcnt / 4;
for (;;) {
status = dw_sdio_reg_read(sdio, DWSDIO_REG_RINTSTS);
if (status & (DWSDIO_INT_DATA_ERR | DWSDIO_INT_DATA_TMO)) {
DBG("%s:, data transfer error!\r\n", __func__);
return E_SYS;
}
if (status & DWSDIO_INT_DTO) {
return E_OK;
}
if (data->flags == SDIO_DATA_READ && (status & DWSDIO_INT_RXDR) && size) {
dw_sdio_fifo_read_poll(sdio, (uint32_t *)data->in, size);
size = 0;
dw_sdio_reg_write(sdio, DWSDIO_REG_RINTSTS, DWSDIO_INT_RXDR);
} else if (data->flags == SDIO_DATA_WRITE && (status & DWSDIO_INT_TXDR) && size) {
dw_sdio_fifo_write_poll(sdio, (uint32_t *)data->out, size);
size = 0;
dw_sdio_reg_write(sdio, DWSDIO_REG_RINTSTS, DWSDIO_INT_TXDR);
}
if ((GET_CUR_MS() - start) > timeout) {
DBG("%s: timeout on data transfer\r\n", __func__);
return E_TMOUT;
}
}
}
void dw_sdio_isr(DEV_SDIO *sdio_obj, void *ptr)
{
uint32_t int_status;
DEV_SDIO_INFO_PTR sdio_info_ptr = &(sdio_obj->sdio_info);
DW_SDIO_CTRL_PTR sdio = (DW_SDIO_CTRL_PTR)sdio_info_ptr->sdio_ctrl;
int_status = dw_sdio_reg_read(sdio, DWSDIO_REG_MINTSTS);
if (int_status & DWSDIO_INT_CAD) {
DBG("SDIO card detected\r\n");
}
if (int_status & DWSDIO_INT_RE) {
DBG("SDIO response error\r\n");
}
if (int_status & DWSDIO_INT_CD) {
DBG("SDIO cmd done\r\n");
}
if (int_status & DWSDIO_INT_TXDR) {
DBG("SDIO tx data request\r\n");
}
if (int_status & DWSDIO_INT_RXDR) {
DBG("SDIO rx data request\r\n");
}
/* clear interrupt */
dw_sdio_reg_write(sdio, DWSDIO_REG_RINTSTS, int_status);
/* \todo dma based interrupt */
}
int32_t dw_sdio_cmd_poll(DEV_SDIO *sdio_obj, SDIO_CMD_PTR cmd, SDIO_DATA_PTR data)
{
DEV_SDIO_INFO_PTR sdio_info_ptr = &(sdio_obj->sdio_info);
DW_SDIO_CTRL_PTR sdio = (DW_SDIO_CTRL_PTR)sdio_info_ptr->sdio_ctrl;
uint32_t start = GET_CUR_MS();
uint32_t timeout = 500;
uint32_t retry = 100000;
uint32_t mask;
uint32_t i;
while (dw_sdio_reg_read(sdio, DWSDIO_REG_STATUS) & DWSDIO_STATUS_DATA_BUSY) {
if ((GET_CUR_MS() - start) > timeout) {
DBG("%s: timeout on data busy\r\n", __func__);
return E_TMOUT;
}
}
dw_sdio_reg_write(sdio, DWSDIO_REG_RINTSTS, DWSDIO_INT_ALL);
if (data) {
dw_sdio_enable_card_threshold(sdio, 1);
dw_sdio_block_size_set(sdio, data->blksz * data->blkcnt, data->blksz);
dw_sdio_reset_wait(sdio, DWSDIO_CTRL_RESET_FIFO);
}
if (dw_sdio_cmd_set(sdio, cmd, data) < 0) {
return E_SYS;
}
for (i = 0; i < retry; i++) {
mask = dw_sdio_reg_read(sdio, DWSDIO_REG_RINTSTS);
if (mask & DWSDIO_INT_CD) {
if (!data) {
dw_sdio_reg_write(sdio, DWSDIO_REG_RINTSTS, mask);
}
break;
}
}
if (i == retry) {
DBG("%s: Timeout.\n", __func__);
return E_TMOUT;
}
if (mask & DWSDIO_INT_RTO) {
/*
* Timeout here is not necessarily fatal. (e)MMC cards
* will splat here when they receive CMD55 as they do
* not support this command and that is exactly the way
* to tell them apart from SD cards. Thus, this output
* below shall be debug(). eMMC cards also do not favor
* CMD8, please keep that in mind.
*/
DBG("%s: Response Timeout:%x.\r\n", __func__, mask);
return E_TMOUT;
} else if (mask & DWSDIO_INT_RE) {
DBG("%s: Response Error:%x.\r\n", __func__, mask);
return E_SYS;
}
if (cmd->resp_type & SDIO_RSP_PRESENT) {
if (cmd->resp_type & SDIO_RSP_136) {
cmd->resp[0] = dw_sdio_reg_read(sdio, DWSDIO_REG_RESP3);
cmd->resp[1] = dw_sdio_reg_read(sdio, DWSDIO_REG_RESP2);
cmd->resp[2] = dw_sdio_reg_read(sdio, DWSDIO_REG_RESP1);
cmd->resp[3] = dw_sdio_reg_read(sdio, DWSDIO_REG_RESP0);
} else {
cmd->resp[0] = dw_sdio_reg_read(sdio, DWSDIO_REG_RESP0);
}
}
if (data) {
return dw_sdio_data_transfer_poll(sdio, data);
}
return E_OK;
}
int32_t dw_sdio_open(DEV_SDIO *sdio_obj, uint32_t card_number)
{
uint32_t fifo_depth;
DEV_SDIO_INFO_PTR sdio_info_ptr = &(sdio_obj->sdio_info);
DW_SDIO_CTRL_PTR sdio = (DW_SDIO_CTRL_PTR)sdio_info_ptr->sdio_ctrl;
if (sdio_info_ptr->opn_cnt > 0) {
dw_sdio_power_on(sdio, card_number);
dw_sdio_reset(sdio, card_number);
dw_sdio_bus_freq_set(sdio, card_number, DWSDIO_ENUMERATION_FREQ);
sdio_info_ptr->opn_cnt++;
return E_OPNED;
}
sdio_info_ptr->opn_cnt++;
dw_sdio_reset_wait(sdio, DWSDIO_CTRL_RESET_ALL);
dw_sdio_ref_clk_set(sdio, sdio->ref_clk);
dw_sdio_power_on(sdio, card_number);
dw_sdio_reset(sdio, card_number);
dw_sdio_bus_type_set(sdio, card_number, 1);
dw_sdio_bus_freq_set(sdio, card_number, DWSDIO_ENUMERATION_FREQ);
if (sdio->fifo_depth == 0) {
fifo_depth = dw_sdio_reg_read(sdio, DWSDIO_REG_FIFOTH);
fifo_depth = ((fifo_depth & DWSDIO_FIFOTH_MASK_RX_WMARK) >>
DWSDIO_FIFOTH_BIT_RX_WMARK) + 1;
sdio->fifo_depth = fifo_depth;
}
fifo_depth = DWSDIO_FIFOTH_M_SIZE(0x2) | DWSDIO_FIFOTH_RX_WMASK(sdio->fifo_depth / 2 - 1) |
DWSDIO_FIFOTH_TX_WMASK(sdio->fifo_depth / 2);
dw_sdio_reg_write(sdio, DWSDIO_REG_FIFOTH, fifo_depth);
return E_OK;
}
int32_t dw_sdio_close(DEV_SDIO *sdio_obj, uint32_t card_number)
{
int32_t ret = E_OK;
DEV_SDIO_INFO_PTR sdio_info_ptr = &(sdio_obj->sdio_info);
DW_SDIO_CTRL_PTR sdio = (DW_SDIO_CTRL_PTR)sdio_info_ptr->sdio_ctrl;
sdio_info_ptr->opn_cnt--;
dw_sdio_power_off(sdio, card_number);
if (sdio_info_ptr->opn_cnt == 0) {
dw_sdio_reset_wait(sdio, DWSDIO_CTRL_RESET_ALL);
} else {
ret = E_OPNED;
}
return ret;
}
int32_t dw_sdio_cd(DEV_SDIO *sdio_obj, uint32_t card_number)
{
uint32_t val;
DEV_SDIO_INFO_PTR sdio_info_ptr = &(sdio_obj->sdio_info);
DW_SDIO_CTRL_PTR sdio = (DW_SDIO_CTRL_PTR)sdio_info_ptr->sdio_ctrl;
/* the card detect depends on the specific PCB lay out.
* Some use 1 (CD pin to VDD) to indicate card detect.
* Some use 0 (CD pin to GNU) to indicate card detect.
*/
#ifdef DWSDIO_CARD_DETECT_HIGH_LEVEL
val = dw_sdio_reg_read(sdio, DWSDIO_REG_CDETECT);
#else
val = ~dw_sdio_reg_read(sdio, DWSDIO_REG_CDETECT);
#endif
if ((val & (1 << card_number)) == (1 << card_number)) {
return 1; /* the specific card detected */
}
return 0;
}
int32_t dw_sdio_wp(DEV_SDIO *sdio_obj, uint32_t card_number)
{
uint32_t val;
DEV_SDIO_INFO_PTR sdio_info_ptr = &(sdio_obj->sdio_info);
DW_SDIO_CTRL_PTR sdio = (DW_SDIO_CTRL_PTR)sdio_info_ptr->sdio_ctrl;
val = dw_sdio_reg_read(sdio, DWSDIO_REG_WRTPRT);
if ((val & (1 << card_number)) == (1 << card_number)) {
return 1; /* the specific card is write-protect */
}
return 0;
}
int32_t dw_sdio_control(DEV_SDIO *sdio_obj, SDIO_CTRL_CMD_PTR ctrl_cmd, void *param)
{
int32_t ret = E_OK;
uint32_t cmd, card;
DEV_SDIO_INFO_PTR sdio_info_ptr = &(sdio_obj->sdio_info);
DW_SDIO_CTRL_PTR sdio = (DW_SDIO_CTRL_PTR)sdio_info_ptr->sdio_ctrl;
cmd = ctrl_cmd->cmd;
card = ctrl_cmd->card;
switch (cmd) {
case SDIO_CMD_SET_BUS_WIDTH:
dw_sdio_bus_type_set(sdio, card, (uint32_t)param);
break;
case SDIO_CMD_SET_BUS_FREQ:
dw_sdio_bus_freq_set(sdio, card, (uint32_t)param);
break;
/* \todo add more cmds */
default:
ret = E_PAR;
}
return ret;
}

View File

@@ -1,364 +0,0 @@
/* ------------------------------------------
* Copyright (c) 2018, 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.
*
--------------------------------------------- */
#include "embARC_toolchain.h"
#include "embARC_error.h"
#include "arc/arc_exception.h"
#include "string.h"
#include "device/designware/dw_nist_trng.h"
#ifdef TRNG_VERSION_NIST
#define DBG_LESS
#include "embARC_debug.h"
#define DW_TRNG_CHECK_EXP(EXPR, ERROR_CODE) CHECK_EXP(EXPR, ercd, ERROR_CODE, error_exit)
#ifndef DISABLE_DEVICE_OBJECT_VALID_CHECK
/** valid check of trng info object */
#define VALID_CHK_TRNG_INFO_OBJECT(trnginfo_obj_ptr) { \
DW_TRNG_CHECK_EXP((trnginfo_obj_ptr) != NULL, E_OBJ); \
DW_TRNG_CHECK_EXP(((trnginfo_obj_ptr)->trng_ctrl) != NULL, E_OBJ); \
}
#endif
#define DW_TRNG_CMD_NOP (0x0)
#define DW_TRNG_CMD_GEN_NOISE (0x1)
#define DW_TRNG_CMD_GEN_NONCE (0x2)
#define DW_TRNG_CMD_CREATE_STATE (0x3)
#define DW_TRNG_CMD_RENEW_STATE (0x4)
#define DW_TRNG_CMD_REFRESH_ADDIN (0x5)
#define DW_TRNG_CMD_GEN_RANDOM (0x6)
#define DW_TRNG_CMD_ADVANCE_STATE (0x7)
#define DW_TRNG_CMD_RUN_KAT (0x8)
#define DW_TRNG_CMD_ZEROIZE (0xF)
/**
* @fn dw_trng_unmask_reg_interrupt(DW_TRNG_REG_PTR trng_reg, uint32_t mask)
* @brief Enable designware trng bit interrupt with mask
*/
Inline void dw_trng_unmask_reg_interrupt(DW_TRNG_REG_PTR trng_reg, uint32_t mask)
{
trng_reg->IE |= mask;
}
/**
* @fn void dw_trng_mask_reg_interrupt(DW_TRNG_REG_PTR trng_reg, uint32_t mask)
* @brief Disable designware trng bit interrupt with mask
*/
Inline void dw_trng_mask_reg_interrupt(DW_TRNG_REG_PTR trng_reg, uint32_t mask)
{
trng_reg->IE &= ~mask;
}
/**
* @fn void dw_trng_wait_till_idle(DW_TRNG_REG_PTR trng_reg)
*/
Inline void dw_trng_wait_till_idle(DW_TRNG_REG_PTR trng_reg)
{
while (trng_reg->stat.busy) {
;
}
}
static int32_t dw_trng_cmd(DEV_TRNG_INFO_PTR trng_info_ptr, uint32_t cmd)
{
int32_t ercd = E_OK;
DW_TRNG_CTRL_PTR trng_ctrl_ptr = trng_info_ptr->trng_ctrl;
DW_TRNG_REG_PTR trng_reg_ptr = (DW_TRNG_REG_PTR) trng_ctrl_ptr->dw_trng_regs;
dw_trng_wait_till_idle(trng_reg_ptr);
switch (cmd) {
case DW_TRNG_CMD_NOP:
case DW_TRNG_CMD_GEN_NOISE:
case DW_TRNG_CMD_GEN_NONCE:
case DW_TRNG_CMD_CREATE_STATE:
case DW_TRNG_CMD_RENEW_STATE:
case DW_TRNG_CMD_REFRESH_ADDIN:
case DW_TRNG_CMD_GEN_RANDOM:
case DW_TRNG_CMD_ADVANCE_STATE:
case DW_TRNG_CMD_RUN_KAT:
case DW_TRNG_CMD_ZEROIZE:
trng_reg_ptr->CTRL |= cmd; break;
default:
ercd = E_PAR; break;
}
return ercd;
}
static void dw_trng_enable_sys_interrupt(DEV_TRNG_INFO_PTR trng_info_ptr)
{
DW_TRNG_CTRL_PTR trng_ctrl_ptr = (DW_TRNG_CTRL_PTR)(trng_info_ptr->trng_ctrl);
trng_ctrl_ptr->int_status |= DW_TRNG_GINT_ENABLE;
if (trng_ctrl_ptr->intno != DW_TRNG_INVALID_INTNO) {
int_handler_install(trng_ctrl_ptr->intno, trng_ctrl_ptr->dw_trng_int_handler);
int_enable(trng_ctrl_ptr->intno);
}
}
static void dw_trng_disable_sys_interrupt(DEV_TRNG_INFO_PTR trng_info_ptr)
{
DW_TRNG_CTRL_PTR trng_ctrl_ptr = (DW_TRNG_CTRL_PTR)(trng_info_ptr->trng_ctrl);
if (trng_ctrl_ptr->intno != DW_TRNG_INVALID_INTNO) {
int_disable(trng_ctrl_ptr->intno);
}
trng_ctrl_ptr->int_status = DW_TRNG_GINT_DISABLE;
}
static int32_t dw_trng_zeroize(DEV_TRNG_INFO_PTR trng_info_ptr)
{
int32_t ercd = E_OK;
// DW_TRNG_CTRL_PTR trng_ctrl_ptr = trng_info_ptr->trng_ctrl;
// DW_TRNG_REG_PTR trng_reg_ptr = (DW_TRNG_REG_PTR) trng_ctrl_ptr->dw_trng_regs;
dw_trng_enable_sys_interrupt(trng_info_ptr);
ercd = dw_trng_cmd(trng_info_ptr, DW_TRNG_CMD_ZEROIZE);
return ercd;
}
static int32_t dw_trng_reseed(DEV_TRNG_INFO_PTR trng_info_ptr, uint32_t *nonce_buf)
{
DW_TRNG_CTRL_PTR trng_ctrl_ptr = trng_info_ptr->trng_ctrl;
DW_TRNG_REG_PTR trng_reg_ptr = (DW_TRNG_REG_PTR) trng_ctrl_ptr->dw_trng_regs;
if (nonce_buf != NULL) {// Nonce Reseed cmd, need to be run 2~3 time with new nonce depending on chosen security algorithm
uint8_t i;
volatile uint32_t *npa_data_ptr = &(trng_reg_ptr->NPA_DATA0);
dw_trng_wait_till_idle(trng_reg_ptr);
for (i = 0; i < 16; i++) {
npa_data_ptr[i] = nonce_buf[i];
}
dw_trng_cmd(trng_info_ptr, DW_TRNG_CMD_GEN_NONCE);
} else {// Random Reseed cmd
dw_trng_cmd(trng_info_ptr, DW_TRNG_CMD_GEN_NOISE);
}
return E_OK;
}
static void dw_trng_get_rand(DW_TRNG_REG_PTR trng_reg_ptr, uint32_t *data) // read from rand0~3
{
if (data != NULL) {
data[0] = trng_reg_ptr->RAND0;
data[1] = trng_reg_ptr->RAND1;
data[2] = trng_reg_ptr->RAND2;
data[3] = trng_reg_ptr->RAND3;
} else {
dbg_printf(DBG_LESS_INFO, "\r\n!DW_TRNG meet invalid memory error: LAST_CMD=0x%x\r\n", trng_reg_ptr->stat.last_cmd);
}
}
static void dw_iic_mst_int_read(DEV_TRNG_PTR trng_obj)
{
DEV_TRNG_INFO_PTR trng_info_ptr = &trng_obj->trng_info;
DW_TRNG_CTRL_PTR trng_ctrl_ptr = trng_info_ptr->trng_ctrl;
DW_TRNG_REG_PTR trng_reg_ptr = (DW_TRNG_REG_PTR) trng_ctrl_ptr->dw_trng_regs;
DEV_BUFFER *buf_ptr = &(trng_info_ptr->out_buf);
uint32_t *p_buf = (uint32_t *)buf_ptr->buf;
if (p_buf != NULL && buf_ptr->len >= buf_ptr->ofs + 4) {// check if buffer has enough space (needs 4 uint32_t per read)
dw_trng_get_rand(trng_reg_ptr, p_buf);
buf_ptr->ofs += 4;
}
if (trng_info_ptr->trng_cbs.out_cb) {
trng_info_ptr->trng_cbs.out_cb(trng_info_ptr);
}
}
int32_t dw_trng_open(DEV_TRNG_PTR trng_obj) // reseed with internal random seed generator
{
int32_t ercd = E_OK;
DW_TRNG_CHECK_EXP(trng_obj != NULL, E_OBJ);
DEV_TRNG_INFO_PTR trng_info_ptr = &trng_obj->trng_info;
VALID_CHK_TRNG_INFO_OBJECT(trng_info_ptr);
DW_TRNG_CTRL_PTR trng_ctrl_ptr = trng_info_ptr->trng_ctrl;
DW_TRNG_REG_PTR trng_reg_ptr = (DW_TRNG_REG_PTR) trng_ctrl_ptr->dw_trng_regs;
trng_reg_ptr->smode.secure_en = 1;// enable mission mode (secure)
/**
* trng interrupt related init
*/
dw_trng_disable_sys_interrupt(trng_info_ptr);
dw_trng_unmask_reg_interrupt(trng_reg_ptr, DW_TRNG_INT_ALL);
dw_trng_zeroize(trng_info_ptr);
// can do a KAT test here to ensure DRBGs are running correctly, need to zeroize afterwards
dw_trng_reseed(trng_info_ptr, NULL);
ercd = dw_trng_cmd(trng_info_ptr, DW_TRNG_CMD_CREATE_STATE);
error_exit:
return ercd;
}
int32_t dw_trng_close(DEV_TRNG_PTR trng_obj)
{
int32_t ercd = E_OK;
DW_TRNG_CHECK_EXP(trng_obj != NULL, E_OBJ);
DEV_TRNG_INFO_PTR trng_info_ptr = &trng_obj->trng_info;
VALID_CHK_TRNG_INFO_OBJECT(trng_info_ptr);
DW_TRNG_CTRL_PTR trng_ctrl_ptr = trng_info_ptr->trng_ctrl;
DW_TRNG_REG_PTR trng_reg_ptr = (DW_TRNG_REG_PTR) trng_ctrl_ptr->dw_trng_regs;
dw_trng_mask_reg_interrupt(trng_reg_ptr, DW_TRNG_INT_ALL);
dw_trng_disable_sys_interrupt(trng_info_ptr);
// clean/release in buffer and out buffer
memset(&(trng_info_ptr->in_buf), 0, sizeof(DEV_BUFFER));
memset(&(trng_info_ptr->out_buf), 0, sizeof(DEV_BUFFER));
memset(&(trng_info_ptr->trng_cbs), 0, sizeof(DEV_TRNG_CBS));
// Do a zeroize for security
dw_trng_cmd(trng_info_ptr, DW_TRNG_CMD_ZEROIZE);
while (!trng_reg_ptr->istat.zeroized) {
; // wait until secure data cleaned
}
trng_reg_ptr->istat.zeroized = 1;
error_exit:
return E_OK;
}
int32_t dw_trng_control(DEV_TRNG_PTR trng_obj, uint32_t ctrl_cmd, void *param)
{
int32_t ercd = E_OK;
DW_TRNG_CHECK_EXP(trng_obj != NULL, E_OBJ);
DEV_TRNG_INFO_PTR trng_info_ptr = &trng_obj->trng_info;
VALID_CHK_TRNG_INFO_OBJECT(trng_info_ptr);
// uint32_t val32; /** to receive unsigned int value */
switch (ctrl_cmd) {
case TRNG_CMD_SET_RAND_RESEED_AUTO:
ercd = dw_trng_cmd(trng_info_ptr, DW_TRNG_CMD_RENEW_STATE);
break;
case TRNG_CMD_SET_RAND_RESEED_NONCE:
ercd = dw_trng_reseed(trng_info_ptr, param);
break;
case TRNG_CMD_SET_IN_CB:
DW_TRNG_CHECK_EXP(CHECK_ALIGN_4BYTES(param), E_PAR);
trng_info_ptr->trng_cbs.in_cb = param;
break;
case TRNG_CMD_SET_OUT_CB:
DW_TRNG_CHECK_EXP(CHECK_ALIGN_4BYTES(param), E_PAR);
trng_info_ptr->trng_cbs.out_cb = param;
break;
case TRNG_CMD_SET_ERR_CB:
DW_TRNG_CHECK_EXP(CHECK_ALIGN_4BYTES(param), E_PAR);
trng_info_ptr->trng_cbs.err_cb = param;
break;
default:
ercd = E_NOSPT;
break;
}
error_exit:
return ercd;
}
int32_t dw_trng_read(DEV_TRNG_PTR trng_obj, uint32_t *data_buf)
{
int32_t ercd = E_OK;
DW_TRNG_CHECK_EXP(trng_obj != NULL, E_OBJ);
DEV_TRNG_INFO_PTR trng_info_ptr = &trng_obj->trng_info;
VALID_CHK_TRNG_INFO_OBJECT(trng_info_ptr);
DW_TRNG_CTRL_PTR trng_ctrl_ptr = trng_info_ptr->trng_ctrl;
DW_TRNG_REG_PTR trng_reg_ptr = (DW_TRNG_REG_PTR) trng_ctrl_ptr->dw_trng_regs;
dw_trng_cmd(trng_info_ptr, DW_TRNG_CMD_GEN_RANDOM);
if (data_buf != NULL) {
dw_trng_wait_till_idle(trng_reg_ptr);
dw_trng_get_rand(trng_reg_ptr, data_buf);
}
error_exit:
return ercd;
}
void dw_trng_isr(DEV_TRNG_PTR trng_obj, void *ptr)
{
int32_t ercd = E_OK;
DW_TRNG_CHECK_EXP(trng_obj != NULL, E_OBJ);
DEV_TRNG_INFO_PTR trng_info_ptr = &(trng_obj->trng_info);
/* START ERROR CHECK */
VALID_CHK_TRNG_INFO_OBJECT(trng_info_ptr);
/* END OF ERROR CHECK */
DW_TRNG_CTRL_PTR trng_ctrl_ptr = trng_info_ptr->trng_ctrl;
DW_TRNG_REG_PTR trng_reg_ptr = (DW_TRNG_REG_PTR) trng_ctrl_ptr->dw_trng_regs;
dbg_printf(DBG_MORE_INFO, "dw_trng_isr ");
if (trng_reg_ptr->alarms.illegal_cmd_seq) {
dbg_printf(DBG_LESS_INFO, "\r\n!DW_TRNG meet illegal_cmd_seq error: LAST_CMD=0x%x\r\n", trng_reg_ptr->stat.last_cmd);
dw_trng_disable_sys_interrupt(trng_info_ptr);
trng_reg_ptr->alarms.illegal_cmd_seq = 1;// Write 1 to clear bit
if (trng_info_ptr->trng_cbs.err_cb) {
trng_info_ptr->trng_cbs.err_cb(trng_info_ptr);
}
}
if (trng_reg_ptr->istat.zeroized) { // zeroize operations can interrupt other operations
trng_reg_ptr->istat.zeroized = 1; // Write 1 to clear bit
dbg_printf(DBG_MORE_INFO, "zeroized");
}
if (trng_reg_ptr->istat.noise_rdy) {
trng_reg_ptr->istat.noise_rdy = 1;// Write 1 to clear bit
dbg_printf(DBG_MORE_INFO, "noise_rdy");
}
if (trng_reg_ptr->istat.done) {
trng_reg_ptr->istat.done = 1;// Write 1 to clear bit
dbg_printf(DBG_MORE_INFO, "done");
if (trng_reg_ptr->stat.last_cmd == DW_TRNG_CMD_GEN_RANDOM) {
dbg_printf(DBG_MORE_INFO, " --- GEN RANDOM done");
trng_info_ptr->byte_generated += 4;// TODO: once too many bytes have been generated, prompt to reseed
dw_iic_mst_int_read(trng_obj);
}
}
if (trng_reg_ptr->istat.alarms) {
trng_reg_ptr->istat.alarms = 1;// Write 1 to clear bit
dbg_printf(DBG_MORE_INFO, "alarms");
}
if (trng_reg_ptr->istat.kat_completed) {
trng_reg_ptr->istat.kat_completed = 1;// Write 1 to clear bit
dbg_printf(DBG_MORE_INFO, "kat_completed");
}
dbg_printf(DBG_MORE_INFO, " #\r\n");
error_exit:
return;
}
#endif /* TRNG_VERSION_NIST */

View File

@@ -1,226 +0,0 @@
/* ------------------------------------------
* Copyright (c) 2018, 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.
*
--------------------------------------------- */
#include "embARC_toolchain.h"
#include "embARC_error.h"
#include "device/designware/dw_trng.h"
#ifndef TRNG_VERSION_NIST
#define DW_TRNG_CHECK_EXP(EXPR, ERROR_CODE) CHECK_EXP(EXPR, ercd, ERROR_CODE, error_exit)
#define DW_TRNG_MODE_R256 0x08
#define DW_TRNG_MODE_R256_OFFSET 3
#define DW_TRNG_ISTAT_RAND_RDY 0x01
#define DW_TRNG_ISTAT_RAND_RDY_OFFSET 0
#define DW_TRNG_ISTAT_SEED_DONE 0x02
#define DW_TRNG_ISTAT_SEED_DONE_OFFSET 1
#define DW_TRNG_ISTAT_AGE_ALARM 0x04
#define DW_TRNG_ISTAT_AGE_ALARM_OFFSET 2
#define DW_TRNG_ISTAT_RQST_ALARM 0x08
#define DW_TRNG_ISTAT_RQST_ALARM_OFFSET 3
#define DW_TRNG_ISTAT_LFSR_LOCKUP 0x10
#define DW_TRNG_ISTAT_LFSR_LOCKUP_OFFSET 4
#define DW_TRNG_CMD_GEN 1
#define DW_TRNG_CMD_RESEED 2
#define DW_TRNG_CMD_NONCE 3
static int32_t dw_trng_cmd(DW_TRNG_REG_PTR trng_reg, uint32_t cmd)
{
int32_t ercd = E_OK;
switch (cmd) {
case DW_TRNG_CMD_GEN:
trng_reg->CTRL |= cmd;
break;
case DW_TRNG_CMD_RESEED:
trng_reg->CTRL |= cmd;
break;
case DW_TRNG_CMD_NONCE:
trng_reg->CTRL |= cmd;
break;
default:
ercd = E_PAR; break;
}
return ercd;
}
inline static int32_t dw_trng_get_mode(DW_TRNG_REG_PTR trng_reg)
{
return (trng_reg->MODE & DW_TRNG_MODE_R256) >> 3;
}
inline static void dw_trng_set_mode(DW_TRNG_REG_PTR trng_reg, uint32_t r256)
{
if (r256) {
trng_reg->MODE |= DW_TRNG_MODE_R256;
} else {
trng_reg->MODE &= ~DW_TRNG_MODE_R256;
}
}
inline static int32_t dw_trng_get_istat_rand_rdy(DW_TRNG_REG_PTR trng_reg)
{
return (trng_reg->ISTAT & DW_TRNG_ISTAT_RAND_RDY) >> DW_TRNG_ISTAT_RAND_RDY_OFFSET;
}
inline static void dw_trng_clear_istat_rand_rdy(DW_TRNG_REG_PTR trng_reg)
{
trng_reg->ISTAT = DW_TRNG_ISTAT_RAND_RDY;// write 1 to clear register bits
}
inline static int32_t dw_trng_get_istat_seed_done(DW_TRNG_REG_PTR trng_reg)
{
return (trng_reg->ISTAT & DW_TRNG_ISTAT_SEED_DONE) >> DW_TRNG_ISTAT_SEED_DONE_OFFSET;
}
inline static void dw_trng_clear_istat_seed_done(DW_TRNG_REG_PTR trng_reg)
{
trng_reg->ISTAT = DW_TRNG_ISTAT_SEED_DONE;// write 1 to clear register bits
}
static void dw_trng_get_rand(DW_TRNG_REG_PTR trng_reg, uint32_t *data) // read from rand0~3 or rand0~7
{
data[0] = trng_reg->RAND0;
data[1] = trng_reg->RAND1;
data[2] = trng_reg->RAND2;
data[3] = trng_reg->RAND3;
// if(dw_trng_get_mode(trng_reg) == 1 )
data[4] = trng_reg->RAND4;
data[5] = trng_reg->RAND5;
data[6] = trng_reg->RAND6;
data[7] = trng_reg->RAND7;
return;
}
static void dw_trng_get_stat(DW_TRNG_REG_PTR trng_reg, uint32_t *stat)
{
*stat = trng_reg->STAT;
return;
}
static int32_t dw_trng_reseed(DW_TRNG_REG_PTR trng_reg, uint32_t *nonce_buf)
{
if (nonce_buf != NULL) {// Nonce Reseed cmd
dw_trng_cmd(trng_reg, DW_TRNG_CMD_NONCE);
// TODO
} else {// Random Reseed cmd
dw_trng_cmd(trng_reg, DW_TRNG_CMD_RESEED);
while (!dw_trng_get_istat_seed_done(trng_reg)) {
// do nothing, wait until reseed is ready
}
dw_trng_clear_istat_seed_done(trng_reg);// clear ISTAT.RAND_RDY bit to acknowledge
}
return E_OK;
}
int32_t dw_trng_open(DEV_TRNG_PTR trng_obj) // reseed with internal random seed generator
{
int32_t ercd = E_OK;
DEV_TRNG_INFO_PTR ptrng_info = &trng_obj->trng_info;
DW_TRNG_CTRL_PTR dw_trng_ctrl_ptr = ptrng_info->trng_ctrl;
DW_TRNG_REG_PTR ptrng = (DW_TRNG_REG_PTR) dw_trng_ctrl_ptr->dw_trng_regs;
dw_trng_reseed(ptrng, NULL);
error_exit:
return ercd;
}
int32_t dw_trng_close(DEV_TRNG_PTR trng_obj) // do nothing
{
return E_OK;
}
int32_t dw_trng_control(DEV_TRNG_PTR trng_obj, uint32_t ctrl_cmd, void *param)
{
int32_t ercd = E_OK;
DEV_TRNG_INFO_PTR ptrng_info = &trng_obj->trng_info;
DW_TRNG_CTRL_PTR dw_trng_ctrl_ptr = ptrng_info->trng_ctrl;
DW_TRNG_REG_PTR ptrng = (DW_TRNG_REG_PTR) dw_trng_ctrl_ptr->dw_trng_regs;
// uint32_t val32; /** to receive unsigned int value */
switch (ctrl_cmd) {
case TRNG_CMD_SET_RAND_128_BIT_OUTPUT:
dw_trng_set_mode(ptrng, 0);
break;
case TRNG_CMD_SET_RAND_256_BIT_OUTPUT:
dw_trng_set_mode(ptrng, 1);
break;
case TRNG_CMD_SET_RAND_RESEED_AUTO:
dw_trng_reseed(ptrng, NULL);
break;
case TRNG_CMD_SET_RAND_RESEED_NONCE:
if (param == NULL) {
ercd = E_PAR;
break;
}
dw_trng_reseed(ptrng, param);
break;
default:
ercd = E_NOSPT;
break;
}
error_exit:
return ercd;
}
int32_t dw_trng_read(DEV_TRNG_PTR trng_obj, uint32_t *data_buf)
{
int32_t ercd = E_OK;
DEV_TRNG_INFO_PTR ptrng_info = &trng_obj->trng_info;
DW_TRNG_CTRL_PTR dw_trng_ctrl_ptr = ptrng_info->trng_ctrl;
DW_TRNG_REG_PTR ptrng = (DW_TRNG_REG_PTR) dw_trng_ctrl_ptr->dw_trng_regs;
dw_trng_cmd(ptrng, DW_TRNG_CMD_GEN);
while (!dw_trng_get_istat_rand_rdy(ptrng)) {
// do nothing, wait until random numbers are ready
}
dw_trng_clear_istat_rand_rdy(ptrng);// clear ISTAT.RAND_RDY bit to acknowledge
dw_trng_get_rand(ptrng, data_buf);
error_exit:
return ercd;
}
void dw_trng_isr(DEV_TRNG_PTR trng_obj, void *ptr)
{
// polling mode, isr not implemented
}
#endif /* TRNG_VERSION_NIST */

View File

@@ -1,958 +0,0 @@
/* ------------------------------------------
* 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.
*
--------------------------------------------- */
#include <string.h>
#include "embARC_toolchain.h"
#include "embARC_error.h"
#include "arc/arc_exception.h"
#include "device/designware/dw_uart_hal.h"
#include "device/designware/dw_uart.h"
/**
* 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))
/**
* 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
};
/**
* @fn int32_t dw_uart_putready(DW_UART_REG *uart_reg_ptr)
* @brief Test whether uart is ready to send, 1 ready, 0 not ready
*/
Inline int32_t dw_uart_putready(DW_UART_REG *uart_reg_ptr)
{
if (uart_reg_ptr->CPR & DW_UART_CPR_FIFO_STAT) {
return ((uart_reg_ptr->USR & DW_UART_USR_TFNF) != 0);
} else {
return ((uart_reg_ptr->LSR & DW_UART_LSR_TXD_EMPTY) != 0);
}
}
/**
* @fn int32_t dw_uart_getready(DW_UART_REG *uart_reg_ptr)
* @brief Test whether uart is ready to receive, 1 ready, 0 not ready
*/
Inline int32_t dw_uart_getready(DW_UART_REG *uart_reg_ptr)
{
if (uart_reg_ptr->CPR & DW_UART_CPR_FIFO_STAT) {
return ((uart_reg_ptr->USR & DW_UART_USR_RFNE) != 0);
} else {
return ((uart_reg_ptr->LSR & DW_UART_LSR_DR) != 0);
}
}
/**
* @fn void dw_uart_putchar(DW_UART_REG *uart_reg_ptr, char chr)
* @brief Write char to uart send fifo
*/
Inline void dw_uart_putchar(DW_UART_REG *uart_reg_ptr, char chr)
{
uart_reg_ptr->DATA = chr;
}
/**
* @fn int32_t dw_uart_getchar(DW_UART_REG *uart_reg_ptr)
* @brief 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;
}
/**
* @fn int32_t dw_uart_snd_chr(DW_UART_REG *uart_reg_ptr, char chr)
* @brief Send char through designware 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 sent
* @retval E_OK Send successfully without any issues
* @retval E_OBJ Device object is 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 E_OK;
}
return E_OBJ;
}
/**
* @fn int32_t dw_uart_rcv_chr(DW_UART_REG *uart_reg_ptr)
* @brief Receive one char through designware uart,
* mostly used in interrupt routine, non-blocked function
* @param[in] uart_reg_ptr Uart register structure pointer
* @return Data received
*/
Inline int32_t dw_uart_rcv_chr(DW_UART_REG *uart_reg_ptr)
{
return dw_uart_getchar(uart_reg_ptr);
}
/**
* @fn void dw_uart_psnd_chr(DW_UART_REG *uart_reg_ptr, char chr)
* @brief Send char through designware uart in poll method, blocked function
* @param[in] uart_reg_ptr Uart register structure pointer
* @param[in] chr Char to 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);
}
/**
* @fn int32_t dw_uart_prcv_chr(DW_UART_REG *uart_reg_ptr)
* @brief Receive one char through designware uart in poll method, blocked function
* @param[in] uart_reg_ptr Uart register structure pointer
* @return Data received
*/
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);
}
/**
* @brief Set designware uart DPS value
* @param uart_reg_ptr Uart register structure pointer
* @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;
/* 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 pointer
* @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);
}
/**
* @fn void dw_uart_software_reset(DW_UART_REG *uart_reg_ptr)
* @brief Do uart software reset
* @param uart_reg_ptr Uart register structure pointer
*/
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 pointer
* @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);
}
}
/**
* @fn void dw_spi_disable(DW_SPI_REG *spi_reg_ptr)
*/
Inline void dw_uart_set_break(DW_UART_REG *uart_reg_ptr)
{
uart_reg_ptr->LCR |= DW_UART_LCR_BREAK;
}
/**
* @fn void dw_uart_clr_break(DW_UART_REG *uart_reg_ptr)
*/
Inline void dw_uart_clr_break(DW_UART_REG *uart_reg_ptr)
{
uart_reg_ptr->LCR &= ~DW_UART_LCR_BREAK;
}
/**
* @brief Initialise designware uart with selected baud rate
* @param[in] uart_reg_ptr Uart register structure pointer
* @param[in] baud_divisor Baud rate
* @param[in] dps Uart databits/parity/stopbits
* @param[in] hwfc Uart flow control method
*/
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 baud rate
* @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;
}
if (uart_reg_ptr->CPR & DW_UART_CPR_FIFO_STAT) {
/* 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] uart_info_ptr Uart information structure pointer
* @param[in] cbrtn Control code of callback routine
*/
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) {
if (uart_ctrl_ptr->intno != DW_UART_INVALID_INTNO) {
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] uart_info_ptr Uart information structure pointer
* @param[in] cbrtn Control code of callback routine
*/
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;
if (uart_ctrl_ptr->intno != DW_UART_INVALID_INTNO) {
int_enable(uart_ctrl_ptr->intno);
}
}
}
}
/**
* @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 */
if (uart_ctrl_ptr->intno != DW_UART_INVALID_INTNO) {
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 Baud rate
* @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;
uint32_t uart_cpr;
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);
uart_cpr = uart_reg_ptr->CPR;
/* Get FIFO Length */
if (uart_cpr & DW_UART_CPR_FIFO_STAT) {
uart_ctrl_ptr->tx_fifo_len = ((uart_cpr & DW_UART_CPR_FIFO_MODE) >> DW_UART_CPR_FIFO_MODE_OFS) << 4;
uart_ctrl_ptr->rx_fifo_len = ((uart_cpr & DW_UART_CPR_FIFO_MODE) >> DW_UART_CPR_FIFO_MODE_OFS) << 4;
} else {
uart_ctrl_ptr->tx_fifo_len = 0;
uart_ctrl_ptr->rx_fifo_len = 0;
}
/** init uart */
uart_info_ptr->baudrate = baud;
baud_divisor = DW_UART_BAUD2DIV(uart_ctrl_ptr->dw_apb_bus_freq, baud);
UART_DPS_FORMAT_DEFAULT(uart_info_ptr->dps_format);
uart_info_ptr->hwfc = UART_FC_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 */
if (uart_ctrl_ptr->intno != DW_UART_INVALID_INTNO) {
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 @ref DEVICE_HAL_UART_CTRLCMD "control command", to change or get some thing related to uart
* @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 to send (data must be char type)
* @param[in] len Data length 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 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;
}

View File

@@ -1,91 +0,0 @@
/* ==========================================================================
* Synopsys DesignWare Sensor and Control IP Subsystem IO Software Driver and
* documentation (hereinafter, "Software") is an Unsupported proprietary work
* of Synopsys, Inc. unless otherwise expressly agreed to in writing between
* Synopsys and you.
*
* The Software IS NOT an item of Licensed Software or Licensed Product under
* any End User Software License Agreement or Agreement for Licensed Product
* with Synopsys or any supplement thereto. You are permitted to use and
* redistribute this Software in source and binary forms, with or without
* modification, provided that redistributions of source code must retain this
* notice. You may not view, use, disclose, copy or distribute this file or
* any information contained herein except pursuant to this license grant from
* Synopsys. If you do not agree with this notice, including the disclaimer
* below, then you are not authorized to use the Software.
*
* THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS 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.
* ========================================================================== */
/*==========================================================================
* Library DW_DFSS-2.1.13
* ========================================================================== */
#include <stdint.h>
#include "device/subsystem/creg_master.h"
#include "io_config.h"
#include "apexextensions.h"
/* determine whether there is at least a single CREG master instance */
#ifdef IO_CREG_MST0_PRESENT
#define CREG_MASTER_DEV_PRESENT
#endif
#ifdef IO_CREG_MST1_PRESENT
#define CREG_MASTER_DEV_PRESENT
#endif
#ifdef IO_CREG_MST2_PRESENT
#define CREG_MASTER_DEV_PRESENT
#endif
#ifdef IO_CREG_MST3_PRESENT
#define CREG_MASTER_DEV_PRESENT
#endif
#ifdef CREG_MASTER_DEV_PRESENT
/* Addresses of CREG master instances */
static const uint32_t creg_masters[4] = {
#ifdef IO_CREG_MST0_PRESENT
AR_IO_CREG_MST0_CTRL,
#else
0,
#endif
#ifdef IO_CREG_MST1_PRESENT
AR_IO_CREG_MST1_CTRL,
#else
0,
#endif
#ifdef IO_CREG_MST2_PRESENT
AR_IO_CREG_MST2_CTRL,
#else
0,
#endif
#ifdef IO_CREG_MST3_PRESENT
AR_IO_CREG_MST3_CTRL,
#else
0,
#endif
};
#define CREG_WRITE(x) _sr((unsigned)(x), (unsigned)creg_masters[dev_id])
#define CREG_READ( ) _lr((unsigned)creg_masters[dev_id])
void io_creg_master_read(uint32_t dev_id, uint32_t *reg_val)
{
*reg_val = CREG_READ();
}
void io_creg_master_write(uint32_t dev_id, uint32_t reg_val)
{
CREG_WRITE(reg_val);
}
#endif

View File

@@ -1,85 +0,0 @@
/* ==========================================================================
* Synopsys DesignWare Sensor and Control IP Subsystem IO Software Driver and
* documentation (hereinafter, "Software") is an Unsupported proprietary work
* of Synopsys, Inc. unless otherwise expressly agreed to in writing between
* Synopsys and you.
*
* The Software IS NOT an item of Licensed Software or Licensed Product under
* any End User Software License Agreement or Agreement for Licensed Product
* with Synopsys or any supplement thereto. You are permitted to use and
* redistribute this Software in source and binary forms, with or without
* modification, provided that redistributions of source code must retain this
* notice. You may not view, use, disclose, copy or distribute this file or
* any information contained herein except pursuant to this license grant from
* Synopsys. If you do not agree with this notice, including the disclaimer
* below, then you are not authorized to use the Software.
*
* THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS 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.
* ========================================================================== */
/*==========================================================================
* Library DW_DFSS-2.1.13
* ========================================================================== */
#include <stdint.h>
#include "device/subsystem/creg_slave.h"
#include "io_config.h"
#include "apexextensions.h"
/* determine whether there is at least a single CREG master instance */
#ifdef IO_CREG_SLV0_PRESENT
#define CREG_SLAVE_DEV_PRESENT
#endif
#ifdef IO_CREG_SLV1_PRESENT
#define CREG_SLAVE_DEV_PRESENT
#endif
#ifdef IO_CREG_SLV2_PRESENT
#define CREG_SLAVE_DEV_PRESENT
#endif
#ifdef IO_CREG_SLV3_PRESENT
#define CREG_SLAVE_DEV_PRESENT
#endif
#ifdef CREG_SLAVE_DEV_PRESENT
/* Addresses of CREG slave instances */
static const uint32_t creg_slaves[4] = {
#ifdef IO_CREG_SLV0_PRESENT
AR_IO_CREG_SLV0_OBSR,
#else
0,
#endif
#ifdef IO_CREG_SLV1_PRESENT
AR_IO_CREG_SLV1_OBSR,
#else
0,
#endif
#ifdef IO_CREG_SLV2_PRESENT
AR_IO_CREG_SLV2_OBSR,
#else
0,
#endif
#ifdef IO_CREG_SLV3_PRESENT
AR_IO_CREG_SLV3_OBSR
#else
0,
#endif
};
#define CREG_READ( ) _lr((unsigned)creg_slaves[dev_id])
void io_creg_slave_read(uint32_t dev_id, uint32_t *reg_val)
{
*reg_val = CREG_READ();
}
#endif

View File

@@ -1,417 +0,0 @@
/* ==========================================================================
* Synopsys DesignWare Sensor and Control IP Subsystem IO Software Driver and
* documentation (hereinafter, "Software") is an Unsupported proprietary work
* of Synopsys, Inc. unless otherwise expressly agreed to in writing between
* Synopsys and you.
*
* The Software IS NOT an item of Licensed Software or Licensed Product under
* any End User Software License Agreement or Agreement for Licensed Product
* with Synopsys or any supplement thereto. You are permitted to use and
* redistribute this Software in source and binary forms, with or without
* modification, provided that redistributions of source code must retain this
* notice. You may not view, use, disclose, copy or distribute this file or
* any information contained herein except pursuant to this license grant from
* Synopsys. If you do not agree with this notice, including the disclaimer
* below, then you are not authorized to use the Software.
*
* THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS 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.
* ========================================================================== */
/*==========================================================================
* Library DW_DFSS-1.1.6
* ========================================================================== */
#include <stdint.h>
#include <stddef.h>
#include <stdlib.h>
#include "device/subsystem/gpio.h"
#include "io_config.h"
#include "apexextensions.h"
/* EIA GPIO device registers */
#define SWPORTA_DR (0x00) /* GPIO Port A Data Register */
#define SWPORTA_DDR (0x04) /* GPIO Port A Data Direction Register */
#define INTEN (0x30) /* GPIO Interrupt Enable Register */
#define INTMASK (0x34) /* GPIO Interrupt Mask Register */
#define INTTYPE_LEVEL (0x38) /* GPIO Interrupt Type Register */
#define INT_POLARITY (0x3c) /* GPIO Interrupt Polarity Register */
#define INTSTATUS (0x44) /* GPIO Interrupt Status Register */
#define DEBOUNCE (0x48) /* GPIO Debounce Enable Register */
#define PORTA_EOI (0x4c) /* GPIO Port A Clear Interrupt Register */
#define EXT_PORTA (0x50) /* GPIO External Port A Register */
#define LS_SYNC (0x60) /* GPIO Level-Sensitive Sync Enable Register */
#define INT_BOTHEDGE (0x68) /* GPIO Both Edge Register */
#define CLKEN (0x80) /* GPIO Clock Enable Register */
typedef _Interrupt void (*ISR) ();
/* Private data structure maintained by the driver. */
typedef struct gpio_info_struct {
uint32_t reg_base; /* base address of device register set */
/* Callbacks */
IO_CB_FUNC rx_cb;
uint8_t opened;
uint8_t instID;
/* Interrupt numbers and handlers */
uint8_t vector; /* GPIO ISR vector */
ISR isr; /* GPIO ISR */
/* Config option */
uint8_t enableDebounce;
} gpio_info_t, *gpio_info_pt;
#ifdef IO_GPIO0_PRESENT
#define GPIO_DEV_PRESENT
#endif
#ifdef IO_GPIO1_PRESENT
#define GPIO_DEV_PRESENT
#endif
#ifdef IO_GPIO2_PRESENT
#define GPIO_DEV_PRESENT
#endif
#ifdef IO_GPIO3_PRESENT
#define GPIO_DEV_PRESENT
#endif
#ifdef IO_GPIO_8B0_PRESENT
#define GPIO_DEV_PRESENT
#endif
#ifdef IO_GPIO_8B1_PRESENT
#define GPIO_DEV_PRESENT
#endif
#ifdef IO_GPIO_8B2_PRESENT
#define GPIO_DEV_PRESENT
#endif
#ifdef IO_GPIO_8B3_PRESENT
#define GPIO_DEV_PRESENT
#endif
#ifdef IO_GPIO_4B0_PRESENT
#define GPIO_DEV_PRESENT
#endif
#ifdef IO_GPIO_4B1_PRESENT
#define GPIO_DEV_PRESENT
#endif
#ifdef IO_GPIO_4B2_PRESENT
#define GPIO_DEV_PRESENT
#endif
#ifdef IO_GPIO_4B3_PRESENT
#define GPIO_DEV_PRESENT
#endif
#ifdef GPIO_DEV_PRESENT
#define GPIO_32_MAX_CNT (4)
#define GPIO_8B_MAX_CNT (4)
#define GPIO_4B_MAX_CNT (4)
#define GPIO_MAX_CNT ((GPIO_32_MAX_CNT) + (GPIO_8B_MAX_CNT) + (GPIO_4B_MAX_CNT))
static void gpio_ISR_proc(uint32_t dev_id);
#ifdef IO_GPIO0_PRESENT
static _Interrupt void gpio0_ISR()
{
gpio_ISR_proc(0);
}
#endif
#ifdef IO_GPIO1_PRESENT
static _Interrupt void gpio1_ISR()
{
gpio_ISR_proc(1);
}
#endif
#ifdef IO_GPIO2_PRESENT
static _Interrupt void gpio2_ISR()
{
gpio_ISR_proc(2);
}
#endif
#ifdef IO_GPIO3_PRESENT
static _Interrupt void gpio3_ISR()
{
gpio_ISR_proc(3);
}
#endif
#ifdef IO_GPIO_8B0_PRESENT
static _Interrupt void gpio_8B_0_ISR()
{
gpio_ISR_proc(0 + GPIO_32_MAX_CNT);
}
#endif
#ifdef IO_GPIO_8B1_PRESENT
static _Interrupt void gpio_8B_1_ISR()
{
gpio_ISR_proc(1 + GPIO_32_MAX_CNT);
}
#endif
#ifdef IO_GPIO_8B2_PRESENT
static _Interrupt void gpio_8B_2_ISR()
{
gpio_ISR_proc(2 + GPIO_32_MAX_CNT);
}
#endif
#ifdef IO_GPIO_8B3_PRESENT
static _Interrupt void gpio_8B_3_ISR()
{
gpio_ISR_proc(3 + GPIO_32_MAX_CNT);
}
#endif
#ifdef IO_GPIO_4B0_PRESENT
static _Interrupt void gpio_4B_0_ISR()
{
gpio_ISR_proc(0 + GPIO_32_MAX_CNT + GPIO_8B_MAX_CNT);
}
#endif
#ifdef IO_GPIO_4B1_PRESENT
static _Interrupt void gpio_4B_1_ISR()
{
gpio_ISR_proc(1 + GPIO_32_MAX_CNT + GPIO_8B_MAX_CNT);
}
#endif
#ifdef IO_GPIO_4B2_PRESENT
static _Interrupt void gpio_4B_2_ISR()
{
gpio_ISR_proc(2 + GPIO_32_MAX_CNT + GPIO_8B_MAX_CNT);
}
#endif
#ifdef IO_GPIO_4B3_PRESENT
static _Interrupt void gpio_4B_3_ISR()
{
gpio_ISR_proc(3 + GPIO_32_MAX_CNT + GPIO_8B_MAX_CNT);
}
#endif
/* GPIO devices private data structures */
static gpio_info_pt gpio_handles[GPIO_MAX_CNT] = { 0 };
static gpio_info_t gpio_devs[] = {
#ifdef IO_GPIO0_PRESENT
{ .instID = IO_GPIO_DEV_ID(0, 32),
.reg_base = AR_IO_GPIO0_SWPORTA_DR,
.vector = IO_GPIO0_INT_INTR_FLAG,
.isr = gpio0_ISR,
.enableDebounce = IO_GPIO0_DEBOUNCE },
#endif
#ifdef IO_GPIO1_PRESENT
{ .instID = IO_GPIO_DEV_ID(1, 32),
.reg_base = AR_IO_GPIO1_SWPORTA_DR,
.vector = IO_GPIO1_INT_INTR_FLAG,
.isr = gpio1_ISR,
.enableDebounce = IO_GPIO1_DEBOUNCE },
#endif
#ifdef IO_GPIO2_PRESENT
{ .instID = IO_GPIO_DEV_ID(2, 32),
.reg_base = AR_IO_GPIO2_SWPORTA_DR,
.vector = IO_GPIO2_INT_INTR_FLAG,
.isr = gpio2_ISR,
.enableDebounce = IO_GPIO2_DEBOUNCE },
#endif
#ifdef IO_GPIO3_PRESENT
{ .instID = IO_GPIO_DEV_ID(3, 32),
.reg_base = AR_IO_GPIO3_SWPORTA_DR,
.vector = IO_GPIO3_INT_INTR_FLAG,
.isr = gpio3_ISR,
.enableDebounce = IO_GPIO3_DEBOUNCE },
#endif
#ifdef IO_GPIO_8B0_PRESENT
{ .instID = IO_GPIO_DEV_ID(0, 8),
.reg_base = AR_IO_GPIO_8B0_SWPORTA_DR,
.vector = IO_GPIO_8B0_INT_INTR_FLAG,
.isr = gpio_8B_0_ISR,
.enableDebounce = IO_GPIO_8B0_DEBOUNCE },
#endif
#ifdef IO_GPIO_8B1_PRESENT
{ .instID = IO_GPIO_DEV_ID(1, 8),
.reg_base = AR_IO_GPIO_8B1_SWPORTA_DR,
.vector = IO_GPIO_8B1_INT_INTR_FLAG,
.isr = gpio_8B_1_ISR,
.enableDebounce = IO_GPIO_8B1_DEBOUNCE },
#endif
#ifdef IO_GPIO_8B2_PRESENT
{ .instID = IO_GPIO_DEV_ID(2, 8),
.reg_base = AR_IO_GPIO_8B2_SWPORTA_DR,
.vector = IO_GPIO_8B2_INT_INTR_FLAG,
.isr = gpio_8B_2_ISR,
.enableDebounce = IO_GPIO_8B2_DEBOUNCE },
#endif
#ifdef IO_GPIO_8B3_PRESENT
{ .instID = IO_GPIO_DEV_ID(3, 8),
.reg_base = AR_IO_GPIO_8B3_SWPORTA_DR,
.vector = IO_GPIO_8B3_INT_INTR_FLAG,
.isr = gpio_8B_3_ISR,
.enableDebounce = IO_GPIO_8B3_DEBOUNCE },
#endif
#ifdef IO_GPIO_4B0_PRESENT
{ .instID = IO_GPIO_DEV_ID(0, 4),
.reg_base = AR_IO_GPIO_4B0_SWPORTA_DR,
.vector = IO_GPIO_4B0_INT_INTR_FLAG,
.isr = gpio_4B_0_ISR,
.enableDebounce = IO_GPIO_4B0_DEBOUNCE },
#endif
#ifdef IO_GPIO_4B1_PRESENT
{ .instID = IO_GPIO_DEV_ID(1, 4),
.reg_base = AR_IO_GPIO_4B1_SWPORTA_DR,
.vector = IO_GPIO_4B1_INT_INTR_FLAG,
.isr = gpio_4B_1_ISR,
.enableDebounce = IO_GPIO_4B1_DEBOUNCE },
#endif
#ifdef IO_GPIO_4B2_PRESENT
{ .instID = IO_GPIO_DEV_ID(2, 4),
.reg_base = AR_IO_GPIO_4B2_SWPORTA_DR,
.vector = IO_GPIO_4B2_INT_INTR_FLAG,
.isr = gpio_4B_2_ISR,
.enableDebounce = IO_GPIO_4B2_DEBOUNCE },
#endif
#ifdef IO_GPIO_4B3_PRESENT
{ .instID = IO_GPIO_DEV_ID(3, 4),
.reg_base = AR_IO_GPIO_4B3_SWPORTA_DR,
.vector = IO_GPIO_4B3_INT_INTR_FLAG,
.isr = gpio_4B_3_ISR,
.enableDebounce = IO_GPIO_4B3_DEBOUNCE },
#endif
{ .instID = GPIO_MAX_CNT }
};
#define REG_WRITE(reg, x) _sr((unsigned)(x), (unsigned)(dev->reg_base + reg))
#define REG_READ(reg) _lr((unsigned)(dev->reg_base + reg))
uint32_t io_gpio_open(uint32_t dev_id)
{
uint32_t h = 0;
gpio_info_pt dev;
h = 0;
while ((gpio_devs[h].instID != dev_id)
&& (gpio_devs[h].instID != GPIO_MAX_CNT)) {
h++;
}
if ((gpio_devs[h].instID == GPIO_MAX_CNT) || (0 != gpio_handles[dev_id])) { /* dev_id not part of design, or still open */
return 1;
}
gpio_handles[dev_id] = &gpio_devs[h];
dev = gpio_handles[dev_id];
dev->opened = 1;
/* enable the clock and enable synchronization */
REG_WRITE(CLKEN, 0x1);
REG_WRITE(LS_SYNC, 0x1);
_setvecti(dev->vector, dev->isr);
return 0;
}
void io_gpio_close(uint32_t dev_id)
{
gpio_info_pt dev = gpio_handles[dev_id];
REG_WRITE(INTEN, 0x0);
REG_WRITE(LS_SYNC, 0x0);
REG_WRITE(CLKEN, 0x0);
_setvecti(dev->vector, NULL);
dev->rx_cb = NULL;
dev->opened = 0;
gpio_handles[dev_id] = 0;
}
void io_gpio_read(uint32_t dev_id, uint32_t *data)
{
gpio_info_pt dev = gpio_handles[dev_id];
*data = REG_READ(EXT_PORTA);
}
void io_gpio_write(uint32_t dev_id, uint32_t data)
{
gpio_info_pt dev = gpio_handles[dev_id];
REG_WRITE(SWPORTA_DR, data);
}
void io_gpio_ioctl(uint32_t dev_id, uint32_t cmd, void *arg)
{
gpio_info_pt dev = gpio_handles[dev_id];
switch (cmd) {
case IO_SET_CB_RX:
dev->rx_cb = ((io_cb_t *) arg)->cb;
break;
case IO_GPIO_SET_DIRECTION:
REG_WRITE(SWPORTA_DDR, *((uint32_t *) arg));
break;
case IO_GPIO_SET_INT_ENABLE:
REG_WRITE(INTEN, *((uint32_t *) arg));
break;
case IO_GPIO_GET_INT_ENABLE:
*((uint32_t *) arg) = REG_READ(INTEN);
break;
case IO_GPIO_SET_INT_MASK:
REG_WRITE(INTMASK, *((uint32_t *) arg));
break;
case IO_GPIO_GET_INT_MASK:
*((uint32_t *) arg) = REG_READ(INTMASK);
break;
case IO_GPIO_SET_INT_TYPE:
REG_WRITE(INTTYPE_LEVEL, *((uint32_t *) arg));
break;
case IO_GPIO_SET_INT_POLARITY:
REG_WRITE(INT_POLARITY, *((uint32_t *) arg));
break;
case IO_GPIO_SET_INT_BOTHEDGE:
REG_WRITE(INT_BOTHEDGE, *((uint32_t *) arg));
break;
case IO_GPIO_SET_DEBOUNCE:
if (dev->enableDebounce == 1) {
REG_WRITE(DEBOUNCE, *((uint32_t *) arg));
}
break;
case IO_GPIO_GET_DIRECTION:
*((uint32_t *) arg) = REG_READ(SWPORTA_DDR);
break;
case IO_GPIO_GET_GPO:
*((uint32_t *) arg) = REG_READ(SWPORTA_DR);
break;
default:
break;
}
}
static void gpio_ISR_proc(uint32_t dev_id)
{
gpio_info_pt dev = gpio_handles[dev_id];
uint32_t status = REG_READ(INTSTATUS);
if (!status) {
return; /* Spurious interrupts. */
}
if (_Usually(NULL != dev->rx_cb)) {
dev->rx_cb(status);
}
REG_WRITE(PORTA_EOI, status); /* clear status register. */
}
#endif

View File

@@ -1,210 +0,0 @@
/* ------------------------------------------
* Copyright (c) 2018, 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.
*
--------------------------------------------- */
/* the wrapper of subsystem gpio driver */
#include "embARC_error.h"
#include "embARC_toolchain.h"
#include "device/subsystem/gpio.h"
#include "device/subsystem/ss_gpio.h"
int32_t ss_gpio_open(SS_GPIO_DEV_CONTEXT *ctx, uint32_t dir)
{
DEV_GPIO_INFO *info = ctx->info;
int32_t ret = E_OK;
io_cb_t cb;
info->opn_cnt++;
if (info->opn_cnt > 1) { /* opened before */
if (dir == info->direction) { /* direction is the same */
return E_OK;
} else { /* open with different direction */
return E_OPNED;
}
}
if (io_gpio_open(ctx->dev_id)) {
return E_SYS;
}
info->direction = dir;
info->method = 0;
ctx->int_bit_type = 0;
ctx->int_bit_polarity = 0;
ctx->int_bit_debounce = 0;
cb.cb = (IO_CB_FUNC)ctx->int_cb;
io_gpio_ioctl(ctx->dev_id, IO_SET_CB_RX, &cb);
io_gpio_ioctl(ctx->dev_id, IO_GPIO_SET_INT_ENABLE, &info->method);
io_gpio_ioctl(ctx->dev_id, IO_GPIO_SET_DIRECTION, &info->direction);
io_gpio_ioctl(ctx->dev_id, IO_GPIO_SET_INT_POLARITY, &ctx->int_bit_polarity);
io_gpio_ioctl(ctx->dev_id, IO_GPIO_SET_DEBOUNCE, &ctx->int_bit_debounce);
int_enable(ctx->intno);
return ret;
}
int32_t ss_gpio_close(SS_GPIO_DEV_CONTEXT *ctx)
{
DEV_GPIO_INFO *info = ctx->info;
info->opn_cnt--;
if (info->opn_cnt == 0) {
io_gpio_close(ctx->dev_id);
int_disable(ctx->intno);
} else {
return E_OPNED;
}
return E_OK;
}
int32_t ss_gpio_control(SS_GPIO_DEV_CONTEXT *ctx, uint32_t ctrl_cmd, void *param)
{
int32_t ret = E_OK;
DEV_GPIO_INFO *info = ctx->info;
DEV_GPIO_INT_CFG *cfg = (DEV_GPIO_INT_CFG *)param;
DEV_GPIO_BIT_ISR *isr = (DEV_GPIO_BIT_ISR *)param;
uint32_t mask;
switch (ctrl_cmd) {
case GPIO_CMD_SET_BIT_DIR_INPUT:
case GPIO_CMD_SET_BIT_DIR_OUTPUT:
if (ctrl_cmd == GPIO_CMD_SET_BIT_DIR_OUTPUT) {
info->direction |= ((uint32_t)param);
} else {
info->direction &= ~((uint32_t)param);
}
io_gpio_ioctl(ctx->dev_id, IO_GPIO_SET_DIRECTION, &(info->direction));
break;
case GPIO_CMD_GET_BIT_DIR:
*((uint32_t *) param) = info->direction;
break;
case GPIO_CMD_ENA_BIT_INT:
case GPIO_CMD_DIS_BIT_INT:
if (ctrl_cmd == GPIO_CMD_ENA_BIT_INT) {
info->method |= ((uint32_t)param);
} else {
info->method &= ~((uint32_t)param);
}
io_gpio_ioctl(ctx->dev_id, IO_GPIO_SET_INT_ENABLE, &(info->method));
if (info->method) {
int_enable(ctx->intno);
} else {
int_disable(ctx->intno);
}
break;
case GPIO_CMD_GET_BIT_MTHD:
io_gpio_ioctl(ctx->dev_id, IO_GPIO_GET_INT_ENABLE, &(info->method));
*((uint32_t *) param) = info->method;
break;
case GPIO_CMD_SET_BIT_INT_CFG:
mask = cfg->int_bit_mask;
ctx->int_bit_type &= ~(mask);
ctx->int_bit_type |= cfg->int_bit_type;
io_gpio_ioctl(ctx->dev_id, IO_GPIO_SET_INT_TYPE, &ctx->int_bit_type);
ctx->int_bit_polarity &= ~(mask);
ctx->int_bit_polarity |= cfg->int_bit_polarity;
io_gpio_ioctl(ctx->dev_id, IO_GPIO_SET_INT_POLARITY, &ctx->int_bit_polarity);
cfg->int_bit_debounce &= mask;
ctx->int_bit_debounce &= ~(mask);
ctx->int_bit_debounce |= cfg->int_bit_debounce;
io_gpio_ioctl(ctx->dev_id, IO_GPIO_SET_DEBOUNCE, &ctx->int_bit_debounce);
break;
case GPIO_CMD_GET_BIT_INT_CFG:
cfg->int_bit_type = ctx->int_bit_type & cfg->int_bit_mask;
cfg->int_bit_polarity = ctx->int_bit_polarity & cfg->int_bit_mask;
cfg->int_bit_debounce = ctx->int_bit_debounce & cfg->int_bit_mask;
break;
case GPIO_CMD_SET_BIT_ISR:
if (isr->int_bit_ofs < ctx->width) {
ctx->handlers[isr->int_bit_ofs] = isr->int_bit_handler;
} else {
ret = E_PAR;
}
break;
case GPIO_CMD_GET_BIT_ISR:
if (isr->int_bit_ofs < ctx->width) {
isr->int_bit_handler = ctx->handlers[isr->int_bit_ofs];
} else {
ret = E_PAR;
}
break;
default:
ret = E_NOSPT;
break;
}
return ret;
}
int32_t ss_gpio_write(SS_GPIO_DEV_CONTEXT *ctx, uint32_t val, uint32_t mask)
{
uint32_t temp_val;
io_gpio_read(ctx->dev_id, &temp_val);
temp_val &= (~mask);
val &= mask;
io_gpio_write(ctx->dev_id, temp_val | val);
return 0;
}
int32_t ss_gpio_read(SS_GPIO_DEV_CONTEXT *ctx, uint32_t *val, uint32_t mask)
{
uint32_t raw;
io_gpio_read(ctx->dev_id, &raw);
*val = raw & mask;
return 0;
}
void ss_gpio_int_cb(SS_GPIO_DEV_CONTEXT *ctx, void *param)
{
DEV_GPIO_INFO *info = ctx->info;
uint32_t i;
for (i = 0; i < ctx->width; i++) {
if ((uint32_t)param & (1 << i) && ctx->handlers[i]) {
ctx->handlers[i](info);
}
}
}

View File

@@ -1,522 +0,0 @@
/* ==========================================================================
* Synopsys DesignWare Sensor and Control IP Subsystem IO Software Driver and
* documentation (hereinafter, "Software") is an Unsupported proprietary work
* of Synopsys, Inc. unless otherwise expressly agreed to in writing between
* Synopsys and you.
*
* The Software IS NOT an item of Licensed Software or Licensed Product under
* any End User Software License Agreement or Agreement for Licensed Product
* with Synopsys or any supplement thereto. You are permitted to use and
* redistribute this Software in source and binary forms, with or without
* modification, provided that redistributions of source code must retain this
* notice. You may not view, use, disclose, copy or distribute this file or
* any information contained herein except pursuant to this license grant from
* Synopsys. If you do not agree with this notice, including the disclaimer
* below, then you are not authorized to use the Software.
*
* THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS 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.
* ========================================================================== */
/*==========================================================================
* Library DW_DFSS-1.1.6
* ========================================================================== */
#include <stdlib.h>
#include <stddef.h>
#include <stdint.h>
#include "device/subsystem/i2s_rx_master.h"
#include "io_config.h"
#include "apexextensions.h"
/* I2S Rx Master device registers */
#define I2S_IER 0x000
#define I2S_IRER 0x004
#define I2S_CER 0x00c
#define I2S_CCR 0x010
#define I2S_RXFFR 0x014
#define I2S_LRBR0 0x020
#define I2S_RRBR0 0x024
#define I2S_RER0 0x028
#define I2S_RCR0 0x030 // Receive configuration register
#define I2S_ISR0 0x038 // Interrupt status register
#define I2S_IMR0 0x03c // Interrupt mask register
#define I2S_ROR0 0x040
#define I2S_RFCR0 0x048
#define I2S_RFF0 0x050
#define I2S_RXDMA 0x1c0
/* I2S Rx Master device specific macros */
#define I2S_RX_MASTER_DMA_CTRL (0xa0000077) /* am=b10, i=b1, dw/inc=b011, dtt=b10, r=b1, op=b11 */
#define I2S_RX_MASTER_DMA_CTRL_SIZE_POS (8)
#define I2S_RX_MASTER_DMA_CTRL_XFER_POS (21)
#define DMA_NONE (0xff)
typedef _Interrupt void (*ISR) ();
typedef struct i2s_rx_master_info_struct {
/* I2S Rx master configuration settings */
const uint32_t reg_base; // base address of device register set
const uint8_t instID; // module instance ID
const uint16_t fifo_size; // FIFO depth
const uint16_t dmachanid; // DMA channel ID
/* I2S data buffer related fields */
uint32_t xfr_len; // number of samples transferred in current buffer
uint32_t xfr_started; // transfer started flag
uint32_t *buffer[2]; // two pointers to the user' buffers
uint32_t *bufsize[2]; // two sizes of user buffers
volatile uint32_t usr_cnt; // user' buffer access counter (incremented from read service)
volatile uint32_t sys_cnt; // system' buffer access counter (incremented from ISR)
#ifdef __Xdmac
_Uncached uint32_t *dmadescriptor; // pointer to the DMA descriptor location
#endif
/* User' callbacks */
IO_CB_FUNC rx_cb; // user' RX completion callback
IO_CB_FUNC err_cb; // user' error callback
/* Interrupt numbers and handlers */
const uint8_t rx_vector; // RX interrupt vector number
const uint8_t err_vector; // RX Error inetrrupt vector number
ISR rx_isr; // I2S data available interrupt handler
ISR err_isr; // I2S FIFO overrun interrupt handler
} i2s_rx_master_info_t, *i2s_rx_master_info_pt;
#ifdef IO_I2S_RX_MST0_PRESENT
#define I2S_RX_MASTER_DEV_PRESENT
#endif
#ifdef IO_I2S_RX_MST1_PRESENT
#define I2S_RX_MASTER_DEV_PRESENT
#endif
#ifdef IO_I2S_RX_MST2_PRESENT
#define I2S_RX_MASTER_DEV_PRESENT
#endif
#ifdef IO_I2S_RX_MST3_PRESENT
#define I2S_RX_MASTER_DEV_PRESENT
#endif
#ifdef IO_I2S_RX_MST4_PRESENT
#define I2S_RX_MASTER_DEV_PRESENT
#endif
#ifdef I2S_RX_MASTER_DEV_PRESENT
#define I2S_RX_MASTER_MAX_CNT (4)
static void i2s_rx_master_rx_ISR_proc(uint32_t dev_id);
static void i2s_rx_master_err_ISR_proc(uint32_t dev_id);
#ifdef IO_I2S_RX_MST0_PRESENT
static _Interrupt void i2s_rx_master0_rx_ISR()
{
i2s_rx_master_rx_ISR_proc(0);
}
static _Interrupt void i2s_rx_master0_err_ISR()
{
i2s_rx_master_err_ISR_proc(0);
}
#endif
#ifdef IO_I2S_RX_MST1_PRESENT
static _Interrupt void i2s_rx_master1_rx_ISR()
{
i2s_rx_master_rx_ISR_proc(1);
}
static _Interrupt void i2s_rx_master1_err_ISR()
{
i2s_rx_master_err_ISR_proc(1);
}
#endif
#ifdef IO_I2S_RX_MST2_PRESENT
static _Interrupt void i2s_rx_master2_rx_ISR()
{
i2s_rx_master_rx_ISR_proc(2);
}
static _Interrupt void i2s_rx_master2_err_ISR()
{
i2s_rx_master_err_ISR_proc(2);
}
#endif
#ifdef IO_I2S_RX_MST3_PRESENT
static _Interrupt void i2s_rx_master3_rx_ISR()
{
i2s_rx_master_rx_ISR_proc(3);
}
static _Interrupt void i2s_rx_master3_err_ISR()
{
i2s_rx_master_err_ISR_proc(3);
}
#endif
/* I2S RX Master devices private data structures */
static i2s_rx_master_info_pt i2s_rx_master_handles[I2S_RX_MASTER_MAX_CNT] =
{ 0 };
#ifdef __Xdmac
static __attribute__ ((aligned(32)))
_Uncached uint32_t i2s_rx_master_dma_descriptors[8 *
I2S_RX_MASTER_MAX_CNT];
#endif
static i2s_rx_master_info_t i2s_rx_master_devs[] = {
#ifdef IO_I2S_RX_MST0_PRESENT
{ .instID = 0,
.reg_base = AR_IO_I2S_RX_MST0_IER,
.rx_vector = IO_I2S_RX_MST0_INT_RX_AVAIL,
.err_vector = IO_I2S_RX_MST0_INT_ERR,
.rx_isr = i2s_rx_master0_rx_ISR,
.err_isr = i2s_rx_master0_err_ISR,
#ifdef IO_I2S_RX_MST0_DMA
.dmachanid = IO_I2S_RX_MST0_DMA,
#else
.dmachanid = DMA_NONE,
#endif
.fifo_size = IO_I2S_RX_MST0_FS },
#endif
#ifdef IO_I2S_RX_MST1_PRESENT
{ .instID = 1,
.reg_base = AR_IO_I2S_RX_MST1_IER,
.rx_vector = IO_I2S_RX_MST1_INT_RX_AVAIL,
.err_vector = IO_I2S_RX_MST1_INT_ERR,
.rx_isr = i2s_rx_master1_rx_ISR,
.err_isr = i2s_rx_master1_err_ISR,
#ifdef IO_I2S_RX_MST1_DMA
.dmachanid = IO_I2S_RX_MST1_DMA,
#else
.dmachanid = DMA_NONE,
#endif
.fifo_size = IO_I2S_RX_MST1_FS },
#endif
#ifdef IO_I2S_RX_MST2_PRESENT
{ .instID = 2,
.reg_base = AR_IO_I2S_RX_MST2_IER,
.rx_vector = IO_I2S_RX_MST2_INT_RX_AVAIL,
.err_vector = IO_I2S_RX_MST2_INT_ERR,
.rx_isr = i2s_rx_master2_rx_ISR,
.err_isr = i2s_rx_master2_err_ISR,
#ifdef IO_I2S_RX_MST2_DMA
.dmachanid = IO_I2S_RX_MST2_DMA,
#else
.dmachanid = DMA_NONE,
#endif
.fifo_size = IO_I2S_RX_MST2_FS },
#endif
#ifdef IO_I2S_RX_MST3_PRESENT
{ .instID = 3,
.reg_base = AR_IO_I2S_RX_MST3_IER,
.rx_vector = IO_I2S_RX_MST3_INT_RX_AVAIL,
.err_vector = IO_I2S_RX_MST3_INT_ERR,
.rx_isr = i2s_rx_master3_rx_ISR,
.err_isr = i2s_rx_master3_err_ISR,
#ifdef IO_I2S_RX_MST3_DMA
.dmachanid = IO_I2S_RX_MST3_DMA,
#else
.dmachanid = DMA_NONE,
#endif
.fifo_size = IO_I2S_RX_MST3_FS },
#endif
{ .instID = I2S_RX_MASTER_MAX_CNT }
};
#define REG_WRITE(reg, x) _sr((uint32_t)((x)), (uint32_t)(dev->reg_base + reg))
#define REG_READ(reg) _lr((uint32_t)(dev->reg_base + (reg)))
/* API functions */
uint32_t io_i2s_rx_master_open(uint32_t dev_id)
{
i2s_rx_master_info_pt dev;
uint32_t h = 0;
/* check device descriptor availability */
while ((i2s_rx_master_devs[h].instID != dev_id)
&& (i2s_rx_master_devs[h].instID != I2S_RX_MASTER_MAX_CNT)) {
h++;
}
if ((i2s_rx_master_devs[h].instID == I2S_RX_MASTER_MAX_CNT) || (0 != i2s_rx_master_handles[dev_id])) { /* dev_id not part of design, or still open */
return 1;
}
i2s_rx_master_handles[dev_id] = &i2s_rx_master_devs[h];
dev = i2s_rx_master_handles[dev_id];
/* initialize driver internal variables */
dev->xfr_started = 0; // clear transfer started flag
dev->xfr_len = 0; // clear transfer length
dev->usr_cnt = dev->sys_cnt = 0; // reset buffer access counters
#ifdef __Xdmac
/* initialize DMA descriptors */
dev->dmadescriptor = &i2s_rx_master_dma_descriptors[8 * h];
if (dev->dmachanid != DMA_NONE) {
dev->dmadescriptor[0] = dev->dmadescriptor[4] = 0;
dev->dmadescriptor[1] = dev->dmadescriptor[5] =
dev->reg_base + I2S_RXDMA;
dev->dmadescriptor[2] = dev->dmadescriptor[6] = 0;
dev->dmadescriptor[3] = (uint32_t) &(dev->dmadescriptor[4]);
dev->dmadescriptor[7] = (uint32_t) &(dev->dmadescriptor[0]);
/* assign DMA interrupt handlers */
_setvecti(dev->err_vector, dev->err_isr);
_setvecti(DMAC_INT_BASE + dev->dmachanid, dev->rx_isr);
_setvecti(DMAC_ERR_BASE + dev->dmachanid, dev->err_isr);
} else {
#endif
/* assign non DMA interrupt handlers */
_setvecti(dev->rx_vector, dev->rx_isr);
_setvecti(dev->err_vector, dev->err_isr);
#ifdef __Xdmac
}
#endif
REG_WRITE(I2S_IER, 0x01); // I2S: enable device
return (0);
}
void io_i2s_rx_master_close(uint32_t dev_id)
{
i2s_rx_master_info_pt dev = i2s_rx_master_handles[dev_id];
/* reset I2S hardware */
REG_WRITE(I2S_IMR0, 0x03); // mask RX interrupts
REG_WRITE(I2S_RER0, 0x01); // reset channel enable to default (1)
REG_WRITE(I2S_CER, 0x00); // disable clk
REG_WRITE(I2S_IRER, 0x00); // disable receive block
REG_WRITE(I2S_RCR0, 0x02); // reset wlen to default (2)
REG_WRITE(I2S_RFCR0, 0x00); // reset threshold
REG_WRITE(I2S_IER, 0x00); // disable device and flushes fifo
#ifdef __Xdmac
/* reset DMA channel */
_dma_chan_enable((0x1 << dev->dmachanid), 0); // aux-DMA channel reset bug fix
_dma_chan_reset(0x1 << dev->dmachanid);
/* deinitialize DMA interrupt handlers */
_setvecti(DMAC_INT_BASE + dev->dmachanid, NULL);
_setvecti(DMAC_ERR_BASE + dev->dmachanid, NULL);
#endif
/* deinitialize non DMA interrupt handlers */
_setvecti(dev->rx_vector, NULL);
_setvecti(dev->err_vector, NULL);
/* reset driver internal variables */
dev->rx_cb = NULL;
dev->err_cb = NULL;
dev->xfr_started = 0;
/* reset device handler */
i2s_rx_master_handles[dev_id] = 0;
}
void io_i2s_rx_master_read(uint32_t dev_id, uint32_t *data,
uint32_t *size)
{
i2s_rx_master_info_pt dev = i2s_rx_master_handles[dev_id];
uint32_t idx = dev->usr_cnt; // copy user access counter to the temporary variable
if (((idx - dev->sys_cnt) != 2) && (*size != 0)) {
idx = idx & 0x0001; // current index in dev->buffer[] & dev->bufsize[]
#ifdef __Xdmac
if (dev->dmachanid != DMA_NONE) {
uint32_t burst_size = (REG_READ(I2S_RFCR0) + 1) << 1; // actual FIFO trigger level
uint32_t xfer_size = (*size) << 2; // transfer size in bytes (ToDo: limited by 8KB)
idx = idx << 2; // calculate available buffer' index
/* DMA: update DMACTRL and DMADAR part of descriptor */
dev->dmadescriptor[idx + 0] =
I2S_RX_MASTER_DMA_CTRL |
(burst_size << I2S_RX_MASTER_DMA_CTRL_XFER_POS) |
((xfer_size - 1) << I2S_RX_MASTER_DMA_CTRL_SIZE_POS);
dev->dmadescriptor[idx + 2] = (uint32_t) data + xfer_size - 2;
if (dev->xfr_started == 0) { /* I2S transfer not yet started -> init DMA and I2S Rx */
dev->xfr_started = 1;
REG_WRITE(I2S_RXFFR, 0x01); // I2S: reset RX FIFO
REG_WRITE(I2S_RFF0, 0x01); // I2S: flush RX FIFO
REG_WRITE(I2S_CER, 0x01); // I2S: start the clock
REG_WRITE(I2S_IRER, 0x01); // I2S: enable receive block
REG_WRITE(I2S_IMR0, ~0x02); // I2S: Unmask RX overrun interrupt
if (dev->dmachanid < DMAC_MEM_CHAN_CNT) {
_dma_chan_desc(dev->dmachanid, &(dev->dmadescriptor[0])); // dev->dmaidx must be 0 !!!
} else {
_dma_chan_desc_aux(dev->dmachanid, &(dev->dmadescriptor[0])); // dev->dmaidx must be 0 !!!
}
/* Start DMA channel / renew descriptor */
_dma_chan_enable((0x1 << dev->dmachanid), 1);
}
} else {
#endif /* __Xdmac */
/* Update data buffer parameters */
dev->buffer[idx] = data;
dev->bufsize[idx] = size;
if (dev->xfr_started == 0) { /* I2S transfer not yet started -> init I2S Rx */
dev->xfr_started = 1;
/* Start I2S non DMA interrupt flow */
REG_WRITE(I2S_RXFFR, 0x01); // I2S: reset RX FIFO
REG_WRITE(I2S_RFF0, 0x01); // I2S: flush RX FIFO
REG_WRITE(I2S_CER, 0x01); // I2S: start the clock
REG_WRITE(I2S_IRER, 0x01); // I2S: enable receive block
REG_WRITE(I2S_IMR0, ~0x03); // I2S: Unmask all RX interrupts
}
#ifdef __Xdmac
}
#endif /* __Xdmac */
dev->usr_cnt++; // update user' buffer access counter
}
}
void io_i2s_rx_master_ioctl(uint32_t dev_id, uint32_t cmd, void *arg)
{
i2s_rx_master_info_pt dev = i2s_rx_master_handles[dev_id];
switch (cmd) {
case IO_SET_CB_RX:
dev->rx_cb = ((io_cb_t *) arg)->cb;
break;
case IO_SET_CB_ERR:
dev->err_cb = ((io_cb_t *) arg)->cb;
break;
case IO_I2S_RX_MASTER_SET_SAMPLE_WIDTH:
/* channel must be disabled before programming I2S_RCR0 */
REG_WRITE(I2S_RCR0, (*(uint32_t *) arg));
break;
case IO_I2S_RX_MASTER_SET_FIFO_THRESHOLD:
/* channel must be disabled before programming I2S_RFCR0 */
REG_WRITE(I2S_RFCR0, (*(uint32_t *) arg));
break;
case IO_I2S_RX_MASTER_SET_BITCLOCK:
REG_WRITE(I2S_CER, *((uint32_t *) arg));
break;
default:
break;
}
}
static uint32_t i2s_rx_master_read_samples(uint32_t dev_id,
uint32_t *count)
{
i2s_rx_master_info_pt dev = i2s_rx_master_handles[dev_id];
uint32_t free_cnt = 0;
if (dev->usr_cnt == dev->sys_cnt) { /* no more data buffer available (buffer underflow error) */
/* if no buffer will be available until FIFO is full then error callback will be called from error ISR */
return (1);
} else {
uint32_t idx = dev->sys_cnt & 0x0001;
uint32_t *buff = dev->buffer[idx];
uint32_t *size = dev->bufsize[idx];
free_cnt = (*size - dev->xfr_len);
if (*count <= free_cnt) { /* enough space in buffer[0] */
free_cnt = *count;
*count = 0;
} else { /* *count > free_cnt: there will be samples remaining for the next buffer */
*count -= free_cnt;
}
/* fill current buffer */
for (int32_t i = 0; i != free_cnt; i++) {
buff[dev->xfr_len + i] = REG_READ(I2S_LRBR0);
buff[dev->xfr_len + i] |= (REG_READ(I2S_RRBR0) << 16);
}
dev->xfr_len += free_cnt;
/* if current buffer is full: rx callback, and increment system counter */
if (dev->xfr_len == *size) {
dev->sys_cnt++;
dev->xfr_len = 0;
if (NULL != dev->rx_cb) {
dev->rx_cb(dev_id);
}
}
}
return (0);
}
/* I2S RX data available interrupt handler */
static void i2s_rx_master_rx_ISR_proc(uint32_t dev_id)
{
i2s_rx_master_info_pt dev = i2s_rx_master_handles[dev_id];
uint32_t sample_cnt = 0;
uint32_t error = 0;
/* Rx FIFO trigger level reached - data available interrupt */
#ifdef __Xdmac
if (dev->dmachanid == DMA_NONE) { /* DMA either disabled or does not exist */
#endif /* __Xdmac */
sample_cnt = REG_READ(I2S_RFCR0) + 1; // actual FIFO trigger level
while (sample_cnt != 0) {
error = i2s_rx_master_read_samples(dev_id, &sample_cnt);
if (error != 0) { /* buffer underrun - no user' buffer left to receive data */
REG_WRITE(I2S_IMR0, 0x0001); // I2S: mask RXDA interrupt
break;
}
}
#ifdef __Xdmac
} else { /* DMA enabled for I2S peripheral */
if (++dev->sys_cnt == dev->usr_cnt) { /* no data buffers left - disable dma channel and mask data available interrupt */
_dma_chan_enable((0x1 << dev->dmachanid), 0);
} else {
// update channel descriptor
_dma_chan_enable((0x1 << dev->dmachanid), 1);
}
if (NULL != dev->rx_cb) { /* call for Rx callback if any */
dev->rx_cb(dev_id);
}
_dma_int_clear((0x1 << dev->dmachanid)); // clear DMA interrupt flag
}
#endif /* __Xdmac */
}
/* I2S RX error (FIFO overflow) interrupt handler */
static void i2s_rx_master_err_ISR_proc(uint32_t dev_id)
{
i2s_rx_master_info_pt dev = i2s_rx_master_handles[dev_id];
/* Rx FIFO overrun case */
#ifdef __Xdmac
if (dev->dmachanid != DMA_NONE) {
/* DMA: disable DMA channel */
_dma_chan_enable((0x1 << dev->dmachanid), 0);
_dma_int_clear((0x1 << dev->dmachanid));
}
#endif
/* I2S: stop I2S device */
REG_WRITE(I2S_IMR0, 0x03); // I2S: mask RX interrupts
REG_WRITE(I2S_CER, 0x00); // I2S: disable clk
REG_WRITE(I2S_IER, 0x00); // I2S: disable device
/* call error callback if any */
if (NULL != dev->err_cb) {
dev->err_cb(dev_id);
}
}
#endif

View File

@@ -1,531 +0,0 @@
/* ==========================================================================
* Synopsys DesignWare Sensor and Control IP Subsystem IO Software Driver and
* documentation (hereinafter, "Software") is an Unsupported proprietary work
* of Synopsys, Inc. unless otherwise expressly agreed to in writing between
* Synopsys and you.
*
* The Software IS NOT an item of Licensed Software or Licensed Product under
* any End User Software License Agreement or Agreement for Licensed Product
* with Synopsys or any supplement thereto. You are permitted to use and
* redistribute this Software in source and binary forms, with or without
* modification, provided that redistributions of source code must retain this
* notice. You may not view, use, disclose, copy or distribute this file or
* any information contained herein except pursuant to this license grant from
* Synopsys. If you do not agree with this notice, including the disclaimer
* below, then you are not authorized to use the Software.
*
* THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS 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.
* ========================================================================== */
/*==========================================================================
* Library DW_DFSS-1.1.6
* ========================================================================== */
#include <stdlib.h>
#include <stddef.h>
#include <stdint.h>
#include "device/subsystem/i2s_tx_master.h"
#include "io_config.h"
#include "apexextensions.h"
/* I2S Tx Master device registers */
#define I2S_IER 0x000
#define I2S_ITER 0x008
#define I2S_CER 0x00c
#define I2S_CCR 0x010
#define I2S_TXFFR 0x018
#define I2S_LTHR 0x020
#define I2S_RTHR 0x024
#define I2S_TER 0x02C
#define I2S_TCR 0x034 // Transmit configuration register
#define I2S_ISR 0x038 // Interrupt status register
#define I2S_IMR 0x03c // Interrupt mask register
#define I2S_TOR 0x044
#define I2S_TFCR 0x04c
#define I2S_TFF 0x054
#define I2S_TXDMA 0x1c8
/* I2S Tx Master device specific macros */
#define I2S_TX_MASTER_DMA_CTRL (0x6000006F) /* am=b01, i=b1, dw/inc=b011, dtt=b01, r=b1, op=b11 */
#define I2S_TX_MASTER_DMA_CTRL_SIZE_POS (8)
#define I2S_TX_MASTER_DMA_CTRL_XFER_POS (21)
#define DMA_NONE (0xff)
typedef _Interrupt void (*ISR) ();
typedef struct i2s_tx_master_info_struct {
/* I2S peripheral configuration values */
const uint32_t reg_base; // base address of device register set
const uint8_t instID; // I2S module instance ID
const uint16_t fifo_size; // FIFO depth
const uint16_t dmachanid; // DMA channel ID
/* I2S data buffer related fields */
uint32_t xfr_len; // number of transferred samples in current buffer
uint32_t xfr_started; // I2S transfer started flag (used for nonDMA xfer)
uint32_t *buffer[2]; // two pointers to the user data buffers
uint32_t *bufsize[2]; // two pointers to the user data buffer sizes
volatile uint32_t sys_cnt; // read access buffer counter (incremented by ISR)
volatile uint32_t usr_cnt; // write access buffer counter (incremented from write service)
#ifdef __Xdmac
_Uncached uint32_t *dmadescriptor; // pointer to DMA descriptors location
#endif
/* User callbacks */
IO_CB_FUNC tx_cb; // user' TX completion callback
IO_CB_FUNC err_cb; // user' error callback
/* Interrupt numbers and handlers */
const uint8_t tx_vector; // TX interrupt vector number
const uint8_t err_vector; // Error interrupt vector number
ISR tx_isr; // I2S data available ISRs
ISR err_isr; // I2S FIFO overrun ISRs
} i2s_tx_master_info_t, *i2s_tx_master_info_pt;
#ifdef IO_I2S_TX_MST0_PRESENT
#define I2S_TX_MASTER_DEV_PRESENT
#endif
#ifdef IO_I2S_TX_MST1_PRESENT
#define I2S_TX_MASTER_DEV_PRESENT
#endif
#ifdef IO_I2S_TX_MST2_PRESENT
#define I2S_TX_MASTER_DEV_PRESENT
#endif
#ifdef IO_I2S_TX_MST3_PRESENT
#define I2S_TX_MASTER_DEV_PRESENT
#endif
#ifdef IO_I2S_TX_MST4_PRESENT
#define I2S_TX_MASTER_DEV_PRESENT
#endif
#ifdef I2S_TX_MASTER_DEV_PRESENT
#define I2S_TX_MASTER_MAX_CNT (4)
static void i2s_tx_master_tx_ISR_proc(uint32_t dev_id);
static void i2s_tx_master_err_ISR_proc(uint32_t dev_id);
#ifdef IO_I2S_TX_MST0_PRESENT
static _Interrupt void i2s_tx_master0_tx_ISR()
{
i2s_tx_master_tx_ISR_proc(0);
}
static _Interrupt void i2s_tx_master0_err_ISR()
{
i2s_tx_master_err_ISR_proc(0);
}
#endif
#ifdef IO_I2S_TX_MST1_PRESENT
static _Interrupt void i2s_tx_master1_tx_ISR()
{
i2s_tx_master_tx_ISR_proc(1);
}
static _Interrupt void i2s_tx_master1_err_ISR()
{
i2s_tx_master_err_ISR_proc(1);
}
#endif
#ifdef IO_I2S_TX_MST2_PRESENT
static _Interrupt void i2s_tx_master2_tx_ISR()
{
i2s_tx_master_tx_ISR_proc(2);
}
static _Interrupt void i2s_tx_master2_err_ISR()
{
i2s_tx_master_err_ISR_proc(2);
}
#endif
#ifdef IO_I2S_TX_MST3_PRESENT
static _Interrupt void i2s_tx_master3_tx_ISR()
{
i2s_tx_master_tx_ISR_proc(3);
}
static _Interrupt void i2s_tx_master3_err_ISR()
{
i2s_tx_master_err_ISR_proc(3);
}
#endif
/* I2S TX Master devices private data structures */
static i2s_tx_master_info_pt i2s_tx_master_handles[I2S_TX_MASTER_MAX_CNT] =
{ 0 };
#ifdef __Xdmac
static __attribute__ ((aligned(32)))
_Uncached uint32_t i2s_tx_master_dma_descriptors[8 *
I2S_TX_MASTER_MAX_CNT];
#endif
static i2s_tx_master_info_t i2s_tx_master_devs[] = {
#ifdef IO_I2S_TX_MST0_PRESENT
{ .instID = 0,
.reg_base = AR_IO_I2S_TX_MST0_IER,
.tx_vector = IO_I2S_TX_MST0_INT_TX_REQ,
.err_vector = IO_I2S_TX_MST0_INT_ERR,
.tx_isr = i2s_tx_master0_tx_ISR,
.err_isr = i2s_tx_master0_err_ISR,
#ifdef IO_I2S_TX_MST0_DMA
.dmachanid = IO_I2S_TX_MST0_DMA,
#else
.dmachanid = DMA_NONE,
#endif
.fifo_size = IO_I2S_TX_MST0_FS },
#endif
#ifdef IO_I2S_TX_MST1_PRESENT
{ .instID = 1,
.reg_base = AR_IO_I2S_TX_MST1_IER,
.tx_vector = IO_I2S_TX_MST1_INT_TX_REQ,
.err_vector = IO_I2S_TX_MST1_INT_ERR,
.tx_isr = i2s_tx_master1_tx_ISR,
.err_isr = i2s_tx_master1_err_ISR,
#ifdef IO_I2S_TX_MST1_DMA
.dmachanid = IO_I2S_TX_MST1_DMA,
#else
.dmachanid = DMA_NONE,
#endif
.fifo_size = IO_I2S_TX_MST1_FS },
#endif
#ifdef IO_I2S_TX_MST2_PRESENT
{ .instID = 2,
.reg_base = AR_IO_I2S_TX_MST2_IER,
.tx_vector = IO_I2S_TX_MST2_INT_TX_REQ,
.err_vector = IO_I2S_TX_MST2_INT_ERR,
.tx_isr = i2s_tx_master2_tx_ISR,
.err_isr = i2s_tx_master2_err_ISR,
#ifdef IO_I2S_TX_MST2_DMA
.dmachanid = IO_I2S_TX_MST2_DMA,
#else
.dmachanid = DMA_NONE,
#endif
.fifo_size = IO_I2S_TX_MST2_FS },
#endif
#ifdef IO_I2S_TX_MST3_PRESENT
{ .instID = 3,
.reg_base = AR_IO_I2S_TX_MST3_IER,
.tx_vector = IO_I2S_TX_MST3_INT_TX_REQ,
.err_vector = IO_I2S_TX_MST3_INT_ERR,
.tx_isr = i2s_tx_master3_tx_ISR,
.err_isr = i2s_tx_master3_err_ISR,
#ifdef IO_I2S_TX_MST3_DMA
.dmachanid = IO_I2S_TX_MST3_DMA,
#else
.dmachanid = DMA_NONE,
#endif
.fifo_size = IO_I2S_TX_MST3_FS },
#endif
{ .instID = I2S_TX_MASTER_MAX_CNT }
};
#define REG_WRITE(reg, x) _sr((uint32_t)((x)), (uint32_t)(dev->reg_base + reg))
#define REG_READ(reg) _lr((uint32_t)(dev->reg_base + (reg)))
/* API functions */
uint32_t io_i2s_tx_master_open(uint32_t dev_id)
{
i2s_tx_master_info_pt dev;
uint32_t h = 0;
/* check device descriptor availability */
while ((i2s_tx_master_devs[h].instID != dev_id)
&& (i2s_tx_master_devs[h].instID != I2S_TX_MASTER_MAX_CNT)) {
h++;
}
if ((i2s_tx_master_devs[h].instID == I2S_TX_MASTER_MAX_CNT) || (0 != i2s_tx_master_handles[dev_id])) { /* dev_id not part of design, or still open */
return 1;
}
i2s_tx_master_handles[dev_id] = &i2s_tx_master_devs[h];
dev = i2s_tx_master_handles[dev_id];
dev->xfr_started = 0; // clear transfer started flag
dev->xfr_len = 0; // clear transfer lenght
dev->sys_cnt = dev->usr_cnt = 0; // reset buffer' access counters
#ifdef __Xdmac
/* initialize DMA descriptors */
dev->dmadescriptor = &i2s_tx_master_dma_descriptors[8 * h];
if (dev->dmachanid != DMA_NONE) {
dev->dmadescriptor[0] = dev->dmadescriptor[4] = 0;
dev->dmadescriptor[1] = dev->dmadescriptor[5] = 0;
dev->dmadescriptor[2] = dev->dmadescriptor[6] =
dev->reg_base + I2S_TXDMA;
dev->dmadescriptor[3] = (uint32_t) &(dev->dmadescriptor[4]);
dev->dmadescriptor[7] = (uint32_t) &(dev->dmadescriptor[0]);
/* assign DMA interrupt vectors */
_setvecti(dev->err_vector, dev->err_isr);
_setvecti(DMAC_INT_BASE + dev->dmachanid, dev->tx_isr);
_setvecti(DMAC_ERR_BASE + dev->dmachanid, dev->err_isr);
} else {
#endif
_setvecti(dev->tx_vector, dev->tx_isr);
_setvecti(dev->err_vector, dev->err_isr);
#ifdef __Xdmac
}
#endif
REG_WRITE(I2S_IER, 0x01); // I2S: enable device
return (0);
}
void io_i2s_tx_master_close(uint32_t dev_id)
{
i2s_tx_master_info_pt dev = i2s_tx_master_handles[dev_id];
/* put I2S registers into "after reset" state */
REG_WRITE(I2S_IMR, 0x30); // mask TX interrupts
REG_WRITE(I2S_TER, 0x00); // disable channel
REG_WRITE(I2S_TFCR, 0x00); // reset threshold to default (0)
REG_WRITE(I2S_TCR, 0x02); // reset wlen to default (2)
REG_WRITE(I2S_TER, 0x01); // reset channel enable to default (1)
REG_WRITE(I2S_CER, 0x00); // disable clk
REG_WRITE(I2S_ITER, 0x00); // disable receive block
REG_WRITE(I2S_IER, 0x00); // disable device and flushes fifo
#ifdef __Xdmac
/* reset DMA channel */
_dma_chan_enable((0x1 << dev->dmachanid), 0); // aux-DMA channel reset bug fix
_dma_chan_reset(0x1 << dev->dmachanid);
/* deinitialize DMA interrupt handlers */
_setvecti(DMAC_INT_BASE + dev->dmachanid, NULL);
_setvecti(DMAC_ERR_BASE + dev->dmachanid, NULL);
#endif
/* deinitialize non DMA interrupt handlers */
_setvecti(dev->tx_vector, NULL);
_setvecti(dev->err_vector, NULL);
/* clear driver internal variables */
dev->tx_cb = NULL;
dev->err_cb = NULL;
dev->xfr_started = 0;
/* reset device handler */
i2s_tx_master_handles[dev_id] = 0;
}
void io_i2s_tx_master_write(uint32_t dev_id, uint32_t *data,
uint32_t *size)
{
i2s_tx_master_info_pt dev = i2s_tx_master_handles[dev_id];
uint32_t idx = dev->usr_cnt;
if (((idx - dev->sys_cnt) != 2) && (*size != 0)) {
idx = idx & 0x0001; // current index in dev->buffer[] & dev->bufsize[]
#ifdef __Xdmac
if (dev->dmachanid != DMA_NONE) {
uint32_t burst_size = (dev->fifo_size - REG_READ(I2S_TFCR)) << 1; // actual FIFO trigger level
uint32_t xfer_size = (*size) << 2; // transfer size in bytes (ToDo: limited by 8KB)
idx = idx << 2; // now this is index in the array of DMA descriptors
/* DMA: update DMACTRL and DMASAR part of descriptor */
dev->dmadescriptor[idx + 0] =
I2S_TX_MASTER_DMA_CTRL |
(burst_size << I2S_TX_MASTER_DMA_CTRL_XFER_POS) |
((xfer_size - 1) << I2S_TX_MASTER_DMA_CTRL_SIZE_POS);
dev->dmadescriptor[idx + 1] = (uint32_t) data + xfer_size - 2;
dev->usr_cnt++; // update user' buffer access counter;
/* init DMA if required */
if (dev->xfr_started == 0) { /* I2S transfer is not yet started -> init I2S Tx and DMA channel */
dev->xfr_started = 1;
REG_WRITE(I2S_TXFFR, 0x01); // I2S: reset TX FIFO
REG_WRITE(I2S_TFF, 0x01); // I2S: flush TX FIFO
REG_WRITE(I2S_CER, 0x01); // I2S: start the clock
REG_WRITE(I2S_ITER, 0x01); // I2S: enable transmitter block
REG_WRITE(I2S_IMR, ~0x20); // I2S: Unmask TX FIFO write overrun interrupts
if (dev->dmachanid < DMAC_MEM_CHAN_CNT) {
_dma_chan_desc(dev->dmachanid,
&(dev->dmadescriptor[0]));
} else {
_dma_chan_desc_aux(dev->dmachanid,
&(dev->dmadescriptor[0]));
}
/* Start DMA channel */
_dma_chan_enable((0x1 << dev->dmachanid), 1);
}
} else {
#endif /* __Xdmac */
/* Store data buffer parameters */
dev->buffer[idx] = data;
dev->bufsize[idx] = size;
dev->usr_cnt++; // update user' buffer access counter;
if (dev->xfr_started == 0) { /* I2S transfer not yet started -> init I2S Rx */
dev->xfr_started = 1;
REG_WRITE(I2S_TXFFR, 0x01); // I2S: reset TX FIFO
REG_WRITE(I2S_TFF, 0x01); // I2S: flush TX FIFO
REG_WRITE(I2S_CER, 0x01); // I2S: start the clock
REG_WRITE(I2S_ITER, 0x01); // I2S: enable transmitter block
REG_WRITE(I2S_IMR, ~0x30); // I2S: Unmask TX interrupts
}
#ifdef __Xdmac
}
#endif /* __Xdmac */
}
}
void io_i2s_tx_master_ioctl(uint32_t dev_id, uint32_t cmd, void *arg)
{
i2s_tx_master_info_pt dev = i2s_tx_master_handles[dev_id];
switch (cmd) {
case IO_SET_CB_TX:
dev->tx_cb = ((io_cb_t *) arg)->cb;
break;
case IO_SET_CB_ERR:
dev->err_cb = ((io_cb_t *) arg)->cb;
break;
case IO_I2S_TX_MASTER_SET_SAMPLE_WIDTH:
/* channel must be disabled before programming I2S_TCR */
REG_WRITE(I2S_TCR, (*(uint32_t *) arg));
break;
case IO_I2S_TX_MASTER_SET_FIFO_THRESHOLD:
/* channel must be disabled before programming I2S_TFCR */
REG_WRITE(I2S_TFCR, (*(uint32_t *) arg));
break;
case IO_I2S_TX_MASTER_SET_BITCLOCK:
REG_WRITE(I2S_CER, *((uint32_t *) arg));
break;
default:
break;
}
}
static uint32_t i2s_tx_master_write_samples(uint32_t dev_id,
uint32_t *count)
{
i2s_tx_master_info_pt dev = i2s_tx_master_handles[dev_id];
uint32_t avail_cnt = 0;
if (dev->sys_cnt == dev->usr_cnt) { /* no more data buffer available (buffer underflow error) */
/* if no buffer will be available until FIFO is full then error callback will be called from error ISR */
return (1);
} else {
uint32_t idx = dev->sys_cnt & 0x0001;
uint32_t *buff = dev->buffer[idx];
uint32_t *size = dev->bufsize[idx];
avail_cnt = (*size - dev->xfr_len);
if (*count <= avail_cnt) { /* enough space in current buffer */
avail_cnt = *count;
*count = 0;
} else { /* *count > avail_cnt: there will be samples remaining for the next buffer */
*count -= avail_cnt;
}
/* fill current buffer */
for (int32_t i = 0; i != avail_cnt; i++) {
REG_WRITE(I2S_LTHR, buff[dev->xfr_len + i]);
REG_WRITE(I2S_RTHR, buff[dev->xfr_len + i] >> 16);
}
dev->xfr_len += avail_cnt;
/* if current buffer is full: call user' callback, and increment read access counter */
if (dev->xfr_len == *size) {
dev->sys_cnt++;
dev->xfr_len = 0;
if (NULL != dev->tx_cb) {
dev->tx_cb(dev_id);
}
}
}
return (0);
}
/* I2S TX data available interrupt handler */
static void i2s_tx_master_tx_ISR_proc(uint32_t dev_id)
{
i2s_tx_master_info_pt dev = i2s_tx_master_handles[dev_id];
uint32_t sample_cnt = 0;
uint32_t error = 0;
/* Tx FIFO trigger level reached - data available interrupt */
#ifdef __Xdmac
if (dev->dmachanid == DMA_NONE) { /* DMA either disabled or does not exist */
#endif /* __Xdmac */
sample_cnt = dev->fifo_size;
if (dev->xfr_started == 0) {
dev->xfr_started = 1;
} else {
sample_cnt -= REG_READ(I2S_TFCR); // available data space in FIFO
}
while (sample_cnt != 0) {
error = i2s_tx_master_write_samples(dev_id, &sample_cnt);
if (error != 0) { /* buffer underrun - no user' buffer left to receive data */
REG_WRITE(I2S_IMR, 0x10); // I2S: mask TXFE interrupt
break;
}
}
#ifdef __Xdmac
} else { /* DMA enabled for I2S peripheral */
if (++dev->sys_cnt == dev->usr_cnt) { /* no data buffers left - disable dma channel and mask data available interrupt */
_dma_chan_enable((0x1 << dev->dmachanid), 0);
} else {
// update buffer descriptor
_dma_chan_enable((0x1 << dev->dmachanid), 1);
}
if (NULL != dev->tx_cb) { /* call for Tx callback if any */
dev->tx_cb(dev_id);
}
_dma_int_clear(0x1 << dev->dmachanid); // clear DMA interrupt flag
}
#endif /* __Xdmac */
}
/* I2S TX error (FIFO overflow) interrupt handler */
static void i2s_tx_master_err_ISR_proc(uint32_t dev_id)
{
i2s_tx_master_info_pt dev = i2s_tx_master_handles[dev_id];
/* Tx FIFO overrun case */
#ifdef __Xdmac
if (dev->dmachanid != DMA_NONE) {
/* DMA: disable DMA channel */
_dma_chan_enable((0x1 << dev->dmachanid), 0);
_dma_int_clear((0x1 << dev->dmachanid));
}
#endif
/* I2S: stop I2S device */
REG_WRITE(I2S_IMR, 0x30); // I2S: mask TX interrupts
REG_WRITE(I2S_CER, 0x00); // I2S: disable clk
REG_WRITE(I2S_IER, 0x00); // I2S: disable device
/* call error callback if any */
if (NULL != dev->err_cb) {
dev->err_cb(dev_id);
}
}
#endif

View File

@@ -1,345 +0,0 @@
/* ------------------------------------------
* Copyright (c) 2018, 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.
*
--------------------------------------------- */
/* the wrapper of subsystem i2s master driver */
#include "embARC_error.h"
#include "embARC_toolchain.h"
#include "device/subsystem/i2s_rx_master.h"
#include "device/subsystem/i2s_tx_master.h"
#include "device/subsystem/ss_i2s_master.h"
/** check expressions used in DFSS I2S driver implementation */
#define SS_I2S_MASTER_CHECK_EXP(EXPR, ERROR_CODE) CHECK_EXP(EXPR, ercd, ERROR_CODE, error_exit)
/* I2S Master device registers */
#define I2S_IER 0x000 /*!< (0x000) : Enable Register */
#define I2S_IRER 0x004 /*!< (0x004) : I2S Receiver Block Enable Register */
#define I2S_ITER 0x008
#define I2S_CER 0x00c /*!< (0x00C) : Clock Enable Register */
#define I2S_CCR 0x010 /*!< (0x010) : Clock Configuration Register */
#define I2S_RXFFR 0x014 /*!< (0x014) : Receiver Block FIFO Register */
#define I2S_TXFFR 0x018
#define I2S_LTHR0 0x020 /*!< (0x020) : Left Transmit Holding Register 0 */
#define I2S_RTHR0 0x024 /*!< (0x024) : Right Transmit Holding Register 0 */
#define I2S_RER0 0x028 /*!< (0x028) : Receive Enable Register 0 */
#define I2S_TER0 0x02C
#define I2S_RCR0 0x030 /*!< (0x030) : Receive Configuration Register 0 */
#define I2S_TCR0 0x034
#define I2S_ISR0 0x038 /*!< (0x038) : Interrupt Status Register 0 */
#define I2S_IMR0 0x03c /*!< (0x03C) : Interrupt Mask Register 0 */
#define I2S_ROR0 0x040 /*!< (0x040) : Receive Overrun Register 0 */
#define I2S_TOR0 0x044
#define I2S_RFCR0 0x048 /*!< (0x048) : Receive FIFO Configuration Register 0 */
#define I2S_RFF0 0x050 /*!< (0x050) : Receive FIFO Flush 0 */
#define I2S_TFF0 0x054
#define I2S_RXDMA 0x1c0 /*!< (0x1C0) : Receiver Block DMA Register */
#define I2S_TXDMA 0x1c8
#define REG_READ(x) arc_aux_read((ctx->reg_base + x))
#define REG_WRITE(x, y) arc_aux_write((ctx->reg_base + x), y)
static void ss_i2s_master_reset(SS_I2S_MST_DEV_CONTEXT *ctx)
{
}
static void ss_i2s_master_flush_tx(SS_I2S_MST_DEV_CONTEXT *ctx)
{
}
static void ss_i2s_master_flush_rx(SS_I2S_MST_DEV_CONTEXT *ctx)
{
}
static void ss_i2s_master_enable(SS_I2S_MST_DEV_CONTEXT *ctx)
{
// enable device
REG_WRITE(I2S_IER, 1);
}
static void ss_i2s_master_disable(SS_I2S_MST_DEV_CONTEXT *ctx)
{
// disable device
REG_WRITE(I2S_IER, 0);
}
int32_t ss_i2s_mst_open(SS_I2S_MST_DEV_CONTEXT *ctx, uint32_t mode, uint32_t param)
{
uint32_t dev_id = ctx->dev_id;
uint8_t io_mode = ctx->io_mode;
DEV_I2S_INFO_PTR info = ctx->info;
io_cb_t callback;
int32_t int_e = 0;
if (mode != DEV_MASTER_MODE) {
return E_PAR;
}
if (info->opn_cnt > 0) {
info->opn_cnt++;
return E_OPNED;
}
info->opn_cnt++;
if (io_mode == SS_I2S_RX) {
if (io_i2s_rx_master_open(dev_id)) {
return E_SYS;
}
callback.cb = (IO_CB_FUNC)ctx->int_rx_cb;
int_e = int_e | int_enable(ctx->int_rx_avil);
int_e = int_e | int_enable(ctx->int_rx_err);
io_i2s_rx_master_ioctl(dev_id, IO_SET_CB_RX, &callback);
} else if (io_mode == SS_I2S_TX) {
if (io_i2s_tx_master_open(dev_id)) {
return E_SYS;
}
callback.cb = (IO_CB_FUNC)ctx->int_tx_cb;
io_i2s_tx_master_ioctl(dev_id, IO_SET_CB_TX, &callback);
int_e = int_e | int_enable(ctx->int_tx_req);
int_e = int_e | int_enable(ctx->int_tx_err);
} else {
return E_SYS;
}
callback.cb = (IO_CB_FUNC)ctx->int_err_cb;
io_i2s_tx_master_ioctl(dev_id, IO_SET_CB_ERR, &callback);
if (int_e != 0) {
return E_PAR;
}
return E_OK;
}
int32_t ss_i2s_mst_close(SS_I2S_MST_DEV_CONTEXT *ctx)
{
DEV_I2S_INFO_PTR info = ctx->info;
uint8_t io_mode = ctx->io_mode;
info->opn_cnt--;
if (info->opn_cnt == 0) {
if (io_mode == SS_I2S_RX) {
int_disable(ctx->int_rx_avil);
int_disable(ctx->int_rx_err);
io_i2s_rx_master_close(ctx->dev_id);
} else if (io_mode == SS_I2S_TX) {
int_disable(ctx->int_tx_req);
int_disable(ctx->int_tx_err);
io_i2s_tx_master_close(ctx->dev_id);
} else {
return E_SYS;
}
info->opn_cnt = 0;
info->status = DEV_DISABLED;
ctx->flags = 0;
} else {
return E_OPNED;
}
return E_OK;
}
int32_t ss_i2s_mst_read(SS_I2S_MST_DEV_CONTEXT *ctx, void *data, uint32_t len)
{
uint32_t dev_id = ctx->dev_id;
uint8_t io_mode = ctx->io_mode;
uint32_t rd_len = len;
if (ctx->flags) {
return E_NORES;
}
if (io_mode == SS_I2S_TX) {
return E_OBJ;
}
if (arc_locked()) {
/*
* not allow to be called in isr or cpu is locked.
* because the bottom driver is simply interrupt driven
*/
return E_SYS;
}
ctx->flags = SS_I2S_MASTER_FLAG_RX;
io_i2s_rx_master_read(dev_id, data, &rd_len);
/* wait finished: i2s master int enable & no cpu lock */
while (ctx->flags & SS_I2S_MASTER_FLAG_RX) {
;
}
if (ctx->flags & SS_I2S_MASTER_FLAG_RX_ERROR) {
ctx->flags = 0;
return E_SYS;
}
return rd_len;
}
int32_t ss_i2s_mst_write(SS_I2S_MST_DEV_CONTEXT *ctx, void *data, uint32_t len)
{
uint32_t dev_id = ctx->dev_id;
uint8_t io_mode = ctx->io_mode;
uint32_t wt_len = len;
if (ctx->flags) {
return E_NORES;
}
if (io_mode == SS_I2S_RX) {
return E_OBJ;
}
if (arc_locked()) {
/*
* not allow to be called in isr or cpu is locked.
* because the bottom driver is simply interrupt driven
*/
return E_SYS;
}
ctx->flags = SS_I2S_MASTER_FLAG_TX;
io_i2s_tx_master_write(dev_id, data, &wt_len);
/* wait finished: i2s master int enable & no cpu lock */
while (ctx->flags & SS_I2S_MASTER_FLAG_TX) {
;
}
if (ctx->flags & SS_I2S_MASTER_FLAG_TX_ERROR) {
ctx->flags = 0;
return E_SYS;
}
return wt_len;
}
int32_t ss_i2s_mst_control(SS_I2S_MST_DEV_CONTEXT *ctx, uint32_t cmd, void *param)
{
uint32_t dev_id = ctx->dev_id;
uint8_t io_mode = ctx->io_mode;
DEV_I2S_INFO_PTR info = ctx->info;
int32_t ercd = E_OK;
io_i2s_rx_master_ioctl(dev_id, cmd, param);
io_i2s_tx_master_ioctl(dev_id, cmd, param);
switch (cmd) {
case I2S_CMD_GET_STATUS:
SS_I2S_MASTER_CHECK_EXP((param != NULL) && CHECK_ALIGN_4BYTES(param), E_PAR);
*((int32_t *)param) = info->status;
break;
case I2S_CMD_SET_TXCB:
if (io_mode == SS_I2S_TX) {
SS_I2S_MASTER_CHECK_EXP(CHECK_ALIGN_4BYTES(param), E_PAR);
io_i2s_tx_master_ioctl(dev_id, IO_SET_CB_TX, param);
}
break;
case I2S_CMD_SET_RXCB:
if (io_mode == SS_I2S_RX) {
SS_I2S_MASTER_CHECK_EXP(CHECK_ALIGN_4BYTES(param), E_PAR);
io_i2s_rx_master_ioctl(dev_id, IO_SET_CB_RX, param);
}
break;
case I2S_CMD_SET_ERRCB:
if (io_mode == SS_I2S_RX) {
SS_I2S_MASTER_CHECK_EXP(CHECK_ALIGN_4BYTES(param), E_PAR);
io_i2s_rx_master_ioctl(dev_id, IO_SET_CB_ERR, param);
} else if (io_mode == SS_I2S_TX) {
SS_I2S_MASTER_CHECK_EXP(CHECK_ALIGN_4BYTES(param), E_PAR);
io_i2s_tx_master_ioctl(dev_id, IO_SET_CB_ERR, param);
}
break;
case I2S_CMD_SET_TXINT: break;
case I2S_CMD_SET_RXINT: break;
case I2S_CMD_RESET:
ss_i2s_master_reset(ctx);
break;
case I2S_CMD_FLUSH_TX:
ss_i2s_master_flush_tx(ctx);
break;
case I2S_CMD_FLUSH_RX:
ss_i2s_master_flush_rx(ctx);
break;
case I2S_CMD_ENA_DEV:
ss_i2s_master_enable(ctx);
break;
case I2S_CMD_DIS_DEV:
ss_i2s_master_disable(ctx);
break;
case I2S_CMD_SET_TXINT_BUF: break;
case I2S_CMD_SET_RXINT_BUF: break;
case I2S_CMD_SET_TXCHET_BUF: break;
case I2S_CMD_SET_RXCHDT_BUF: break;
case I2S_CMD_MST_SET_CLK: break;
case I2S_CMD_MST_SET_WSS: break;
case I2S_CMD_MST_SET_SCLKG: break;
default:
ercd = E_NOSPT;
break;
}
error_exit:
return ercd;
}
void ss_i2s_mst_int_tx_cb(SS_I2S_MST_DEV_CONTEXT *ctx, void *param)
{
DEV_I2S_INFO_PTR info = ctx->info;
if (ctx->flags & SS_I2S_MASTER_FLAG_TX) {
ctx->flags &= ~SS_I2S_MASTER_FLAG_TX;
if (info->i2s_cbs.tx_cb) {
info->i2s_cbs.tx_cb(info);
}
}
}
void ss_i2s_mst_int_rx_cb(SS_I2S_MST_DEV_CONTEXT *ctx, void *param)
{
DEV_I2S_INFO_PTR info = ctx->info;
if (ctx->flags & SS_I2S_MASTER_FLAG_RX) {
ctx->flags &= ~SS_I2S_MASTER_FLAG_RX;
if (info->i2s_cbs.rx_cb) {
info->i2s_cbs.rx_cb(info);
}
}
}
void ss_i2s_mst_int_err_cb(SS_I2S_MST_DEV_CONTEXT *ctx, void *param)
{
DEV_I2S_INFO_PTR info = ctx->info;
uint8_t io_mode = ctx->io_mode;
uint32_t flag;
flag = (io_mode == SS_I2S_RX) ? SS_I2S_MASTER_FLAG_RX_ERROR : SS_I2S_MASTER_FLAG_TX_ERROR;
if (ctx->flags & flag) {
ctx->flags &= ~flag;
if (info->i2s_cbs.err_cb) {
info->i2s_cbs.err_cb(info);
}
}
}

View File

@@ -1,947 +0,0 @@
/* ==========================================================================
* Synopsys DesignWare Sensor and Control IP Subsystem IO Software Driver and
* documentation (hereinafter, "Software") is an Unsupported proprietary work
* of Synopsys, Inc. unless otherwise expressly agreed to in writing between
* Synopsys and you.
*
* The Software IS NOT an item of Licensed Software or Licensed Product under
* any End User Software License Agreement or Agreement for Licensed Product
* with Synopsys or any supplement thereto. You are permitted to use and
* redistribute this Software in source and binary forms, with or without
* modification, provided that redistributions of source code must retain this
* notice. You may not view, use, disclose, copy or distribute this file or
* any information contained herein except pursuant to this license grant from
* Synopsys. If you do not agree with this notice, including the disclaimer
* below, then you are not authorized to use the Software.
*
* THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS 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.
* ========================================================================== */
/*==========================================================================
* Library DW_DFSS-1.1.6
* ========================================================================== */
#include <stdint.h>
#include <stddef.h>
#include <stdlib.h>
#include "device/subsystem/i2c_master.h"
#include "device/subsystem/i2c_priv.h"
#include "io_config.h"
#include "apexextensions.h"
/* Notes:
*
*/
#ifdef IO_I2C_MST0_PRESENT
#define I2C_DEV_PRESENT
#endif
#ifdef IO_I2C_MST1_PRESENT
#define I2C_DEV_PRESENT
#endif
#ifdef IO_I2C_MST2_PRESENT
#define I2C_DEV_PRESENT
#endif
#ifdef IO_I2C_MST3_PRESENT
#define I2C_DEV_PRESENT
#endif
#ifdef I2C_DEV_PRESENT
#define I2C_MAX_CNT (4)
static void i2c_mst_err_ISR_proc(uint32_t dev_id);
static void i2c_mst_rx_avail_ISR_proc(uint32_t dev_id);
static void i2c_mst_tx_req_ISR_proc(uint32_t dev_id);
static void i2c_mst_stop_det_ISR_proc(uint32_t dev_id);
#ifdef IO_I2C_MST0_PRESENT
static _Interrupt void i2c_mst0_err_ISR()
{
i2c_mst_err_ISR_proc(0);
}
static _Interrupt void i2c_mst0_rx_avail_ISR()
{
i2c_mst_rx_avail_ISR_proc(0);
}
static _Interrupt void i2c_mst0_tx_req_ISR()
{
i2c_mst_tx_req_ISR_proc(0);
}
static _Interrupt void i2c_mst0_stop_det_ISR()
{
i2c_mst_stop_det_ISR_proc(0);
}
#endif
#ifdef IO_I2C_MST1_PRESENT
static _Interrupt void i2c_mst1_err_ISR()
{
i2c_mst_err_ISR_proc(1);
}
static _Interrupt void i2c_mst1_rx_avail_ISR()
{
i2c_mst_rx_avail_ISR_proc(1);
}
static _Interrupt void i2c_mst1_tx_req_ISR()
{
i2c_mst_tx_req_ISR_proc(1);
}
static _Interrupt void i2c_mst1_stop_det_ISR()
{
i2c_mst_stop_det_ISR_proc(1);
}
#endif
#ifdef IO_I2C_MST2_PRESENT
static _Interrupt void i2c_mst2_err_ISR()
{
i2c_mst_err_ISR_proc(2);
}
static _Interrupt void i2c_mst2_rx_avail_ISR()
{
i2c_mst_rx_avail_ISR_proc(2);
}
static _Interrupt void i2c_mst2_tx_req_ISR()
{
i2c_mst_tx_req_ISR_proc(2);
}
static _Interrupt void i2c_mst2_stop_det_ISR()
{
i2c_mst_stop_det_ISR_proc(2);
}
#endif
#ifdef IO_I2C_MST3_PRESENT
static _Interrupt void i2c_mst3_err_ISR()
{
i2c_mst_err_ISR_proc(3);
}
static _Interrupt void i2c_mst3_rx_avail_ISR()
{
i2c_mst_rx_avail_ISR_proc(3);
}
static _Interrupt void i2c_mst3_tx_req_ISR()
{
i2c_mst_tx_req_ISR_proc(3);
}
static _Interrupt void i2c_mst3_stop_det_ISR()
{
i2c_mst_stop_det_ISR_proc(3);
}
#endif
static void fill_txfifo(i2c_info_pt dev);
static void fill_txfifo_for_rx(i2c_info_pt dev);
static void retrieve_rxfifo(i2c_info_pt dev);
#ifdef __Xdmac
static void create_dma_descriptors_rx(i2c_info_pt dev, uint8_t *dest,
uint32_t size, uint32_t burst);
static void create_dma_descriptors_tx(i2c_info_pt dev, uint8_t *src,
uint32_t size, uint32_t burst);
static void create_dma_descriptors_tx_for_rx(i2c_info_pt dev,
uint32_t size,
uint32_t burst);
#endif
/* I2C master devices private data structures */
static i2c_info_pt i2c_handles[I2C_MAX_CNT] = { 0 };
#ifdef __Xdmac
static _Uncached uint32_t i2c_dmarx_descriptors[4 * I2C_MAX_CNT];
static _Uncached uint32_t i2c_dmatx_descriptors[8 * I2C_MAX_CNT];
#endif
static i2c_info_t i2c_master_devs[] = {
#ifdef IO_I2C_MST0_PRESENT
{ .instID = 0,
.reg_base = AR_IO_I2C_MST0_CON,
#ifdef IO_I2C_MST0_DMA_RX
.dmarxchanid = IO_I2C_MST0_DMA_RX,
#else
.dmarxchanid = DMA_NONE,
#endif
#ifdef IO_I2C_MST0_DMA_TX
.dmatxchanid = IO_I2C_MST0_DMA_TX,
#else
.dmatxchanid = DMA_NONE,
#endif
.fifo_depth = IO_I2C_MST0_FS,
.vector_err = IO_I2C_MST0_INT_ERR,
.isr_err = i2c_mst0_err_ISR,
.vector_rx_avail = IO_I2C_MST0_INT_RX_AVAIL,
.isr_rx_avail = i2c_mst0_rx_avail_ISR,
.vector_tx_req = IO_I2C_MST0_INT_TX_REQ,
.isr_tx_req = i2c_mst0_tx_req_ISR,
.vector_stop_det = IO_I2C_MST0_INT_STOP_DET,
.isr_stop_det = i2c_mst0_stop_det_ISR },
#endif
#ifdef IO_I2C_MST1_PRESENT
{ .instID = 1,
.reg_base = AR_IO_I2C_MST1_CON,
#ifdef IO_I2C_MST1_DMA_RX
.dmarxchanid = IO_I2C_MST1_DMA_RX,
#else
.dmarxchanid = DMA_NONE,
#endif
#ifdef IO_I2C_MST1_DMA_TX
.dmatxchanid = IO_I2C_MST1_DMA_TX,
#else
.dmatxchanid = DMA_NONE,
#endif
.fifo_depth = IO_I2C_MST1_FS,
.vector_err = IO_I2C_MST1_INT_ERR,
.isr_err = i2c_mst1_err_ISR,
.vector_rx_avail = IO_I2C_MST1_INT_RX_AVAIL,
.isr_rx_avail = i2c_mst1_rx_avail_ISR,
.vector_tx_req = IO_I2C_MST1_INT_TX_REQ,
.isr_tx_req = i2c_mst1_tx_req_ISR,
.vector_stop_det = IO_I2C_MST1_INT_STOP_DET,
.isr_stop_det = i2c_mst1_stop_det_ISR },
#endif
#ifdef IO_I2C_MST2_PRESENT
{ .instID = 2,
.reg_base = AR_IO_I2C_MST2_CON,
#ifdef IO_I2C_MST2_DMA_RX
.dmarxchanid = IO_I2C_MST2_DMA_RX,
#else
.dmarxchanid = DMA_NONE,
#endif
#ifdef IO_I2C_MST2_DMA_TX
.dmatxchanid = IO_I2C_MST2_DMA_TX,
#else
.dmatxchanid = DMA_NONE,
#endif
.fifo_depth = IO_I2C_MST2_FS,
.vector_err = IO_I2C_MST2_INT_ERR,
.isr_err = i2c_mst2_err_ISR,
.vector_rx_avail = IO_I2C_MST2_INT_RX_AVAIL,
.isr_rx_avail = i2c_mst2_rx_avail_ISR,
.vector_tx_req = IO_I2C_MST2_INT_TX_REQ,
.isr_tx_req = i2c_mst2_tx_req_ISR,
.vector_stop_det = IO_I2C_MST2_INT_STOP_DET,
.isr_stop_det = i2c_mst2_stop_det_ISR },
#endif
#ifdef IO_I2C_MST3_PRESENT
{ .instID = 3,
.reg_base = AR_IO_I2C_MST3_CON,
#ifdef IO_I2C_MST3_DMA_RX
.dmarxchanid = IO_I2C_MST3_DMA_RX,
#else
.dmarxchanid = DMA_NONE,
#endif
#ifdef IO_I2C_MST3_DMA_TX
.dmatxchanid = IO_I2C_MST3_DMA_TX,
#else
.dmatxchanid = DMA_NONE,
#endif
.fifo_depth = IO_I2C_MST3_FS,
.vector_err = IO_I2C_MST3_INT_ERR,
.isr_err = i2c_mst3_err_ISR,
.vector_rx_avail = IO_I2C_MST3_INT_RX_AVAIL,
.isr_rx_avail = i2c_mst3_rx_avail_ISR,
.vector_tx_req = IO_I2C_MST3_INT_TX_REQ,
.isr_tx_req = i2c_mst3_tx_req_ISR,
.vector_stop_det = IO_I2C_MST3_INT_STOP_DET,
.isr_stop_det = i2c_mst3_stop_det_ISR },
#endif
{ .instID = I2C_MAX_CNT }
};
#define REG_WRITE(reg, x) _sr((unsigned)(x), (unsigned)(dev->reg_base + reg))
#define REG_READ(reg) _lr((unsigned)(dev->reg_base + reg))
#define REG_WRITE_BITS(reg, x, y, len, pos) REG_WRITE(reg, ((((x) & ~((~(0xffffffff << len)) << pos)) \
| (((y) << pos) & ((~(0xffffffff << len)) << pos)))))
/* API functions */
uint32_t io_i2c_master_open(uint32_t dev_id)
{
uint32_t h = 0;
i2c_info_pt dev;
h = 0;
while ((i2c_master_devs[h].instID != dev_id)
&& (i2c_master_devs[h].instID != I2C_MAX_CNT)) {
h++;
}
if ((i2c_master_devs[h].instID == I2C_MAX_CNT) || (0 != i2c_handles[dev_id])) { /* dev_id not part of design, or still open */
return 1;
}
i2c_handles[dev_id] = &i2c_master_devs[h];
dev = i2c_handles[dev_id];
/* enable clock */
REG_WRITE(I2C_CLKEN, 0x1);
/* mask all interrupts */
REG_WRITE(I2C_INTR_MASK, 0);
/* initialize */
dev->handling_tx = dev->handling_rx = 0;
dev->tx_data = dev->rx_data = NULL;
dev->next_cond = I2C_STOP_CMD;
/* set interrupt vector */
_setvecti(dev->vector_err, dev->isr_err);
_setvecti(dev->vector_rx_avail, dev->isr_rx_avail);
_setvecti(dev->vector_tx_req, dev->isr_tx_req);
_setvecti(dev->vector_stop_det, dev->isr_stop_det);
#ifdef __Xdmac
dev->dmarxdescriptor = &i2c_dmarx_descriptors[4 * h];
dev->dmatxdescriptor = &i2c_dmatx_descriptors[8 * h];
if (dev->dmarxchanid != DMA_NONE) {
dev->dmarxdescriptor[1] = dev->reg_base + I2C_DATA_CMD;
dev->dmarxdescriptor[3] = 0;
_setvecti(DMAC_INT_BASE + dev->dmarxchanid, dev->isr_rx_avail);
_setvecti(DMAC_ERR_BASE + dev->dmarxchanid, dev->isr_err);
}
if (dev->dmatxchanid != DMA_NONE) {
dev->dmatxdescriptor[2] = dev->dmatxdescriptor[6] =
dev->reg_base + I2C_DATA_CMD;
dev->dmatxdescriptor[3] = (uint32_t) &(dev->dmatxdescriptor[4]);
dev->dmatxdescriptor[7] = 0;
_setvecti(DMAC_INT_BASE + dev->dmatxchanid, dev->isr_tx_req);
_setvecti(DMAC_ERR_BASE + dev->dmatxchanid, dev->isr_err);
}
#endif
/* enable device */
REG_WRITE(I2C_ENABLE, 0x1);
/* unmask error interrupt: stop-detection, tx-abort, rx-over */
REG_WRITE(I2C_INTR_MASK, R_TX_ABRT | R_RX_OVER);
return 0;
}
void io_i2c_master_close(uint32_t dev_id)
{
i2c_info_pt dev = i2c_handles[dev_id];
uint32_t enable = REG_READ(I2C_ENABLE);
/* clear all interrupts */
REG_WRITE(I2C_INTR_MASK, 0);
REG_READ(I2C_CLR_INTR);
/* abort (and wait) */
REG_WRITE(I2C_ENABLE, (enable | (0x1 << 1)));
while ((REG_READ(I2C_TX_ABRT_SOURCE) & (0x1 << 16)) == 0) {
;
}
/* disable */
REG_WRITE(I2C_ENABLE, 0);
/* reset regs */
REG_WRITE(I2C_CON, 0x65);
REG_WRITE(I2C_TAR, 0x55);
REG_WRITE(I2C_SS_SCL_HCNT, 0x30);
REG_WRITE(I2C_SS_SCL_LCNT, 0x38);
REG_WRITE(I2C_FS_SCL_HCNT, 0);
REG_WRITE(I2C_FS_SCL_LCNT, 0);
REG_WRITE(I2C_RX_TL, 0);
REG_WRITE(I2C_TX_TL, 0);
REG_WRITE(I2C_SDA_HOLD, 0x1);
REG_WRITE(I2C_FS_SPKLEN, 0x1);
/* gate the I2C clock */
REG_WRITE(I2C_CLKEN, 0);
_setvecti(dev->vector_err, NULL);
_setvecti(dev->vector_rx_avail, NULL);
_setvecti(dev->vector_tx_req, NULL);
_setvecti(dev->vector_stop_det, NULL);
#ifdef __Xdmac
if (dev->dmarxchanid != DMA_NONE) {
_setvecti(DMAC_INT_BASE + dev->dmarxchanid, NULL);
_setvecti(DMAC_ERR_BASE + dev->dmarxchanid, NULL);
_dma_chan_reset(0x1 << dev->dmarxchanid);
}
if (dev->dmatxchanid != DMA_NONE) {
_setvecti(DMAC_INT_BASE + dev->dmatxchanid, NULL);
_setvecti(DMAC_ERR_BASE + dev->dmatxchanid, NULL);
_dma_chan_reset(0x1 << dev->dmatxchanid);
}
#endif
dev->rx_cb = NULL;
dev->tx_cb = NULL;
dev->err_cb = NULL;
i2c_handles[dev_id] = 0;
}
void io_i2c_master_read(uint32_t dev_id, uint8_t *data, uint32_t *size)
{
i2c_info_pt dev = i2c_handles[dev_id];
uint32_t val = 0;
dev->rx_size = *size;
dev->rx_count = dev->rx_req_count = 0;
dev->rx_data = data;
/* check whether a master-tx is in progress; if so, postpone until tx completion */
if (dev->handling_tx == 0) {
dev->handling_rx = 1;
#ifdef __Xdmac
if (dev->dmarxchanid == DMA_NONE) {
#endif
/* write first requests to fifo, assuming size > 0 */
fill_txfifo_for_rx(dev);
/* unmask interrupts: tx-threshold (tx-empty), rx-threshold (rx-full) */
val = REG_READ(I2C_INTR_MASK) | R_TX_EMPTY | R_RX_FULL;
REG_WRITE(I2C_INTR_MASK, val);
#ifdef __Xdmac
} else {
/* RX descriptor - to fetch data */
if (*size != 0) {
/* rx data available; at least one */
create_dma_descriptors_rx(dev, data, *size,
(1 + REG_READ(I2C_RX_TL)));
/* init dma */
if (dev->dmarxchanid < DMAC_MEM_CHAN_CNT) {
_dma_chan_desc(dev->dmarxchanid,
&(dev->dmarxdescriptor[0]));
} else {
_dma_chan_desc_aux(dev->dmarxchanid,
&(dev->dmarxdescriptor[0]));
}
_dma_chan_enable((0x1 << dev->dmarxchanid), 1);
}
/* TX descriptor - for read command and a closing read+stop command */
if (*size != 0) {
/* tx data available; at least one, more is uncertain */
create_dma_descriptors_tx_for_rx(dev, *size,
(dev->fifo_depth -
REG_READ(I2C_TX_TL)));
/* init dma */
if (dev->dmatxchanid < DMAC_MEM_CHAN_CNT) {
_dma_chan_desc(dev->dmatxchanid,
&(dev->dmatxdescriptor[0]));
} else {
_dma_chan_desc_aux(dev->dmatxchanid,
&(dev->dmatxdescriptor[0]));
}
_dma_chan_enable((0x1 << dev->dmatxchanid), 1);
}
}
#endif
}
}
void io_i2c_master_write(uint32_t dev_id, uint8_t *data, uint32_t *size)
{
i2c_info_pt dev = i2c_handles[dev_id];
uint32_t val = 0;
dev->tx_size = *size;
dev->tx_count = 0;
dev->tx_data = data;
/* check whether a master-rx is in progress; if so, postpone until rx completion */
if (dev->handling_rx == 0) {
dev->handling_tx = 1;
#ifdef __Xdmac
if (dev->dmatxchanid == DMA_NONE) {
#endif
/* write first bytes to fifo, assuming size > 0 */
fill_txfifo(dev);
/* unmask interrupt: tx-threshold (tx-empty) */
val = REG_READ(I2C_INTR_MASK) | R_TX_EMPTY;
REG_WRITE(I2C_INTR_MASK, val);
#ifdef __Xdmac
} else {
/* TX descriptor - data+write command and a closing data+write+stop command */
if (*size != 0) {
/* tx data available; at least one, more is uncertain */
create_dma_descriptors_tx(dev, data, *size,
(dev->fifo_depth -
REG_READ(I2C_TX_TL)));
/* init dma */
if (dev->dmatxchanid < DMAC_MEM_CHAN_CNT) {
_dma_chan_desc(dev->dmatxchanid,
&(dev->dmatxdescriptor[0]));
} else {
_dma_chan_desc_aux(dev->dmatxchanid,
&(dev->dmatxdescriptor[0]));
}
_dma_chan_enable((0x1 << dev->dmatxchanid), 1);
}
}
#endif
}
}
void io_i2c_master_ioctl(uint32_t dev_id, uint32_t cmd, void *arg)
{
uint32_t data = 0, enable = 0;
i2c_info_pt dev = i2c_handles[dev_id];
switch (cmd) {
case IO_SET_CB_RX:
dev->rx_cb = ((io_cb_t *) arg)->cb;
break;
case IO_SET_CB_TX:
dev->tx_cb = ((io_cb_t *) arg)->cb;
break;
case IO_SET_CB_ERR:
dev->err_cb = ((io_cb_t *) arg)->cb;
break;
case IO_I2C_MASTER_SET_NEXT_COND:
dev->next_cond = (uint16_t)*((uint32_t *) arg);
break;
default:
{
enable = REG_READ(I2C_ENABLE);
REG_WRITE(I2C_ENABLE, (enable & ~(0x1)));
switch (cmd) {
case IO_I2C_MASTER_SET_HOLD_TIME_RX:
data = REG_READ(I2C_SDA_HOLD);
REG_WRITE_BITS(I2C_SDA_HOLD, data, *((uint32_t *) arg), 8,
16);
break;
case IO_I2C_MASTER_SET_HOLD_TIME_TX:
data = REG_READ(I2C_SDA_HOLD);
REG_WRITE_BITS(I2C_SDA_HOLD, data, *((uint32_t *) arg), 16,
0);
break;
case IO_I2C_MASTER_SET_SPEED:
data = REG_READ(I2C_CON);
REG_WRITE_BITS(I2C_CON, data, *((uint32_t *) arg), 2, 1);
break;
case IO_I2C_MASTER_SET_10BIT_ADDR:
data = REG_READ(I2C_CON);
REG_WRITE_BITS(I2C_CON, data, *((uint32_t *) arg), 1, 3);
break;
case IO_I2C_MASTER_SET_SPKLEN:
REG_WRITE(I2C_FS_SPKLEN, *((uint32_t *) arg));
break;
case IO_I2C_MASTER_SET_TARGET_ADDR:
REG_WRITE(I2C_TAR, *((uint32_t *) arg));
break;
case IO_I2C_MASTER_SET_SS_SCL_HCNT:
REG_WRITE(I2C_SS_SCL_HCNT, *((uint32_t *) arg));
break;
case IO_I2C_MASTER_SET_SS_SCL_LCNT:
REG_WRITE(I2C_SS_SCL_LCNT, *((uint32_t *) arg));
break;
case IO_I2C_MASTER_SET_FS_SCL_HCNT:
REG_WRITE(I2C_FS_SCL_HCNT, *((uint32_t *) arg));
break;
case IO_I2C_MASTER_SET_FS_SCL_LCNT:
REG_WRITE(I2C_FS_SCL_LCNT, *((uint32_t *) arg));
break;
case IO_I2C_MASTER_SET_RX_THRESHOLD:
REG_WRITE(I2C_RX_TL, *((uint32_t *) arg));
break;
case IO_I2C_MASTER_SET_TX_THRESHOLD:
REG_WRITE(I2C_TX_TL, *((uint32_t *) arg));
break;
default:
break;
}
while ((0x1 & REG_READ(I2C_ENABLE_STATUS)) != 0) {
;
}
enable = REG_READ(I2C_ENABLE);
REG_WRITE(I2C_ENABLE, (enable | 0x1));
break;
}
}
}
static void i2c_mst_err_ISR_proc(uint32_t dev_id)
{
i2c_info_pt dev = i2c_handles[dev_id];
if (REG_READ(I2C_CLR_TX_ABRT)) {
if (NULL != dev->err_cb) {
dev->err_cb(dev_id);
}
}
if (REG_READ(I2C_CLR_RX_OVER)) {
if (NULL != dev->err_cb) {
dev->err_cb(dev_id);
}
}
}
static void i2c_mst_rx_avail_ISR_proc(uint32_t dev_id)
{
i2c_info_pt dev = i2c_handles[dev_id];
uint32_t val = 0;
#ifdef __Xdmac
if (dev->dmarxchanid == DMA_NONE) {
#endif
/* read data from fifo */
retrieve_rxfifo(dev);
if (dev->rx_size == dev->rx_count) { /* read buffer completely filled, mask rx-avail interrupt */
val = REG_READ(I2C_INTR_MASK) & ~R_RX_FULL;
REG_WRITE(I2C_INTR_MASK, val);
dev->handling_rx = 0;
dev->rx_data = NULL;
if (NULL != dev->rx_cb) {
dev->rx_cb(dev_id);
}
}
#ifdef __Xdmac
} else {
/* DMA RX xfer done */
_dma_chan_enable((0x1 << dev->dmarxchanid), 0);
_dma_int_clear((0x1 << dev->dmarxchanid));
}
#endif
}
static void i2c_mst_tx_req_ISR_proc(uint32_t dev_id)
{
i2c_info_pt dev = i2c_handles[dev_id];
uint32_t val = 0;
if (dev->handling_tx == 1) {
#ifdef __Xdmac
if (dev->dmatxchanid == DMA_NONE) {
#endif
if (dev->tx_size == dev->tx_count) { /* no data left to put into the fifo, mask tx-threshold (tx-empty) */
val = REG_READ(I2C_INTR_MASK) & ~R_TX_EMPTY;
REG_WRITE(I2C_INTR_MASK, val);
/* tx done */
dev->handling_tx = 0;
dev->tx_data = NULL;
if (NULL != dev->tx_cb) {
dev->tx_cb(dev_id);
}
} else { /* write data into fifo */
fill_txfifo(dev);
}
#ifdef __Xdmac
} else {
/* DMA TX xfer done */
_dma_chan_enable((0x1 << dev->dmatxchanid), 0);
_dma_int_clear((0x1 << dev->dmatxchanid));
}
#endif
}
if (dev->handling_rx == 1) {
#ifdef __Xdmac
if (dev->dmatxchanid == DMA_NONE) {
#endif
if (dev->rx_size == dev->rx_req_count) { /* no data left to put into the fifo, mask tx-threshold (tx-empty) */
val = REG_READ(I2C_INTR_MASK) & ~R_TX_EMPTY;
REG_WRITE(I2C_INTR_MASK, val);
} else { /* write data into fifo */
fill_txfifo_for_rx(dev);
}
#ifdef __Xdmac
} else {
/* DMA TX xfer done */
dev->rx_req_count = dev->rx_size;
_dma_chan_enable((0x1 << dev->dmatxchanid), 0);
_dma_int_clear((0x1 << dev->dmatxchanid));
}
#endif
}
}
static void i2c_mst_stop_det_ISR_proc(uint32_t dev_id)
{
i2c_info_pt dev = i2c_handles[dev_id];
uint32_t val = 0;
if (dev->handling_tx == 1) {
/* tx done */
dev->handling_tx = 0;
dev->tx_data = NULL;
if (NULL != dev->tx_cb) {
dev->tx_cb(dev_id);
}
/* handle pending rx, if any */
if (dev->rx_data != NULL) {
dev->handling_rx = 1;
#ifdef __Xdmac
if (dev->dmarxchanid == DMA_NONE) {
#endif
/* write first requests to fifo, assuming size > 0 */
fill_txfifo_for_rx(dev);
/* unmask interrupts: tx-threshold (tx-empty), rx-threshold (rx-full) */
val = REG_READ(I2C_INTR_MASK) | R_TX_EMPTY | R_RX_FULL;
REG_WRITE(I2C_INTR_MASK, val);
#ifdef __Xdmac
} else {
/* RX descriptor - to fetch data */
if (dev->rx_size != 0) {
/* rx data available; at least one */
create_dma_descriptors_rx(dev, dev->rx_data,
dev->rx_size,
(1 + REG_READ(I2C_RX_TL)));
/* init dma */
if (dev->dmarxchanid < DMAC_MEM_CHAN_CNT) {
_dma_chan_desc(dev->dmarxchanid,
&(dev->dmarxdescriptor[0]));
} else {
_dma_chan_desc_aux(dev->dmarxchanid,
&(dev->dmarxdescriptor[0]));
}
_dma_chan_enable((0x1 << dev->dmarxchanid), 1);
}
/* TX descriptor - for read command and a closing read+stop command */
if (dev->rx_size != 0) {
/* tx data available; at least one, more is uncertain */
create_dma_descriptors_tx_for_rx(dev, dev->rx_size,
(dev->fifo_depth -
REG_READ
(I2C_TX_TL)));
/* init dma */
if (dev->dmatxchanid < DMAC_MEM_CHAN_CNT) {
_dma_chan_desc(dev->dmatxchanid,
&(dev->dmatxdescriptor[0]));
} else {
_dma_chan_desc_aux(dev->dmatxchanid,
&(dev->dmatxdescriptor[0]));
}
_dma_chan_enable((0x1 << dev->dmatxchanid), 1);
}
}
#endif
} else { /* done, prevent threshold interrupts */
val = REG_READ(I2C_INTR_MASK) & ~R_TX_EMPTY & ~R_RX_FULL;
REG_WRITE(I2C_INTR_MASK, val);
}
} else if (dev->handling_rx == 1) {
#ifdef __Xdmac
if (dev->dmarxchanid == DMA_NONE) {
#endif
/* read remaining data from fifo */
retrieve_rxfifo(dev);
#ifdef __Xdmac
}
#endif
/* rx done */
dev->handling_rx = 0;
dev->rx_data = NULL;
if (NULL != dev->rx_cb) {
dev->rx_cb(dev_id);
}
/* handle pending tx, if any */
if (dev->tx_data != NULL) {
dev->handling_tx = 1;
#ifdef __Xdmac
if (dev->dmatxchanid == DMA_NONE) {
#endif
/* write first bytes to fifo, assuming size > 0 */
fill_txfifo(dev);
/* unmask interrupt: tx-threshold (tx-empty) */
val = REG_READ(I2C_INTR_MASK) | R_TX_EMPTY;
REG_WRITE(I2C_INTR_MASK, val);
#ifdef __Xdmac
} else {
/* TX descriptor - data+write command and a closing data+write+stop command */
if (dev->tx_size != 0) {
/* tx data available; at least one, more is uncertain */
create_dma_descriptors_tx(dev, dev->tx_data,
dev->tx_size,
(dev->fifo_depth -
REG_READ(I2C_TX_TL)));
/* init dma */
if (dev->dmatxchanid < DMAC_MEM_CHAN_CNT) {
_dma_chan_desc(dev->dmatxchanid,
&(dev->dmatxdescriptor[0]));
} else {
_dma_chan_desc_aux(dev->dmatxchanid,
&(dev->dmatxdescriptor[0]));
}
_dma_chan_enable((0x1 << dev->dmatxchanid), 1);
}
}
#endif
} else { /* done, prevent threshold interrupts */
val = REG_READ(I2C_INTR_MASK) & ~R_TX_EMPTY & ~R_RX_FULL;
REG_WRITE(I2C_INTR_MASK, val);
}
}
REG_READ(I2C_CLR_STOP_DET);
}
static void fill_txfifo(i2c_info_pt dev)
{
uint32_t h = 0, free = 0, cnt = 0;
cnt = dev->tx_size - dev->tx_count;
free = dev->fifo_depth - REG_READ(I2C_TXFLR);
if (cnt > free) {
cnt = free;
}
for (h = 0; h != (cnt - 1); h++) {
REG_WRITE(I2C_DATA_CMD, (dev->tx_data[dev->tx_count++]));
}
if ((dev->tx_size - 1) == dev->tx_count) { /* end of message, insert stop condition */
REG_WRITE(I2C_DATA_CMD,
(dev->tx_data[dev->tx_count++] | dev->next_cond));
} else { /* continue */
REG_WRITE(I2C_DATA_CMD, (dev->tx_data[dev->tx_count++]));
}
}
static void fill_txfifo_for_rx(i2c_info_pt dev)
{
uint32_t h = 0, free = 0, cnt = 0;
cnt = dev->rx_size - dev->rx_req_count;
free = dev->fifo_depth - REG_READ(I2C_TXFLR);
if (cnt > free) {
cnt = free;
}
for (h = 0; h != (cnt - 1); h++) {
REG_WRITE(I2C_DATA_CMD, I2C_READ_CMD);
}
dev->rx_req_count += cnt;
if (dev->rx_size == dev->rx_req_count) { /* end of message, insert stop condition */
REG_WRITE(I2C_DATA_CMD, (I2C_READ_CMD | dev->next_cond));
} else { /* continue */
REG_WRITE(I2C_DATA_CMD, I2C_READ_CMD);
}
}
static void retrieve_rxfifo(i2c_info_pt dev)
{
uint32_t h = 0, avail = 0, cnt = 0;
cnt = dev->rx_size - dev->rx_count;
avail = REG_READ(I2C_RXFLR);
if (cnt > avail) {
cnt = avail;
}
for (h = 0; h != cnt; h++) {
dev->rx_data[dev->rx_count++] = REG_READ(I2C_DATA_CMD);
}
}
#ifdef __Xdmac
#define I2C_MST_DMA_RX_CTRL (0xa0000015) /* am=b10, i=b1, dw/inc=b000, dtt=b10, r=b1, op=b01 */
#define I2C_MST_DMA_TX_FOR_RX_CTRL (0x0000006f) /* am=b00, i=b0, dw/inc=b011, dtt=b01, r=b1, op=b11 */
#define I2C_MST_DMA_TX_END_CTRL (0x2000006d) /* am=b00, i=b1, dw/inc=b011, dtt=b01, r=b1, op=b01 */
#define I2C_MST_DMA_TX_CTRL (0x4000000f) /* am=b01, i=b0, dw/inc=b000, dtt=b01, r=b1, op=b11 */
#define I2C_MST_DMA_CTRL_SIZE_POS (8)
#define I2C_MST_DMA_CTRL_XFER_POS (21)
static uint16_t readCommand = I2C_READ_CMD;
static uint16_t readstopCommand = I2C_READ_CMD | I2C_STOP_CMD;
static void create_dma_descriptors_rx(i2c_info_pt dev, uint8_t *dest,
uint32_t size, uint32_t burst)
{
dev->dmarxdescriptor[0] =
I2C_MST_DMA_RX_CTRL | (burst << I2C_MST_DMA_CTRL_XFER_POS) |
((size - 1) << I2C_MST_DMA_CTRL_SIZE_POS);
dev->dmarxdescriptor[2] = (uint32_t) dest + (size - 1);
}
static void create_dma_descriptors_tx(i2c_info_pt dev, uint8_t *src,
uint32_t size, uint32_t burst)
{
if (size > 1) {
dev->dmatxdescriptor[0] =
I2C_MST_DMA_TX_CTRL | (burst << I2C_MST_DMA_CTRL_XFER_POS) |
((size - 2) << I2C_MST_DMA_CTRL_SIZE_POS);
dev->dmatxdescriptor[1] = (uint32_t) src + (size - 2);
dev->dmatx_last = src[size - 1] | I2C_STOP_CMD;
dev->dmatxdescriptor[4 + 0] =
I2C_MST_DMA_TX_END_CTRL | (burst << I2C_MST_DMA_CTRL_XFER_POS)
| (1 << I2C_MST_DMA_CTRL_SIZE_POS);
dev->dmatxdescriptor[4 + 1] = (uint32_t) &(dev->dmatx_last);
} else { /* size == 1 */
dev->dmatx_last = src[0] | I2C_STOP_CMD;
dev->dmatxdescriptor[0] =
I2C_MST_DMA_TX_END_CTRL | (burst << I2C_MST_DMA_CTRL_XFER_POS)
| (1 << I2C_MST_DMA_CTRL_SIZE_POS);
dev->dmatxdescriptor[1] = (uint32_t) &(dev->dmatx_last);
}
}
static void create_dma_descriptors_tx_for_rx(i2c_info_pt dev,
uint32_t size, uint32_t burst)
{
if (size > 1) {
dev->dmatxdescriptor[0] =
I2C_MST_DMA_TX_FOR_RX_CTRL | (burst <<
I2C_MST_DMA_CTRL_XFER_POS) |
(((size - 1) * 2 - 1) << I2C_MST_DMA_CTRL_SIZE_POS);
dev->dmatxdescriptor[1] = (uint32_t) &readCommand;
dev->dmatxdescriptor[4 + 0] =
I2C_MST_DMA_TX_END_CTRL | (burst << I2C_MST_DMA_CTRL_XFER_POS)
| (1 << I2C_MST_DMA_CTRL_SIZE_POS);
dev->dmatxdescriptor[4 + 1] = (uint32_t) &readstopCommand;
} else { /* size == 1 */
dev->dmatxdescriptor[0] =
I2C_MST_DMA_TX_END_CTRL | (burst << I2C_MST_DMA_CTRL_XFER_POS)
| (1 << I2C_MST_DMA_CTRL_SIZE_POS);
dev->dmatxdescriptor[1] = (uint32_t) &readstopCommand;
}
}
#endif
#endif

View File

@@ -1,690 +0,0 @@
/* ==========================================================================
* Synopsys DesignWare Sensor and Control IP Subsystem IO Software Driver and
* documentation (hereinafter, "Software") is an Unsupported proprietary work
* of Synopsys, Inc. unless otherwise expressly agreed to in writing between
* Synopsys and you.
*
* The Software IS NOT an item of Licensed Software or Licensed Product under
* any End User Software License Agreement or Agreement for Licensed Product
* with Synopsys or any supplement thereto. You are permitted to use and
* redistribute this Software in source and binary forms, with or without
* modification, provided that redistributions of source code must retain this
* notice. You may not view, use, disclose, copy or distribute this file or
* any information contained herein except pursuant to this license grant from
* Synopsys. If you do not agree with this notice, including the disclaimer
* below, then you are not authorized to use the Software.
*
* THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS 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.
* ========================================================================== */
/*==========================================================================
* Library DW_DFSS-1.1.6
* ========================================================================== */
#include <stdint.h>
#include <stddef.h>
#include <stdlib.h>
#include "device/subsystem/i2c_slave.h"
#include "device/subsystem/i2c_priv.h"
#include "io_config.h"
#include "apexextensions.h"
/* Notes:
*
*/
#ifdef IO_I2C_SLV0_PRESENT
#define I2C_DEV_PRESENT
static _Interrupt void i2c_slv0_err_ISR();
static _Interrupt void i2c_slv0_rx_avail_ISR();
static _Interrupt void i2c_slv0_tx_req_ISR();
static _Interrupt void i2c_slv0_stop_det_ISR();
static _Interrupt void i2c_slv0_rd_req_ISR();
/* I2C slave devices private data structures; at most 1 instance */
static i2c_info_pt i2c_handles[1] = { 0 };
#ifdef __Xdmac
static _Uncached uint32_t i2c_dmarx_descriptors[4 * 1];
static _Uncached uint32_t i2c_dmatx_descriptors[8 * 1];
#endif
#define I2C_SLV_DMA_RX_CTRL (0xa0000015) /* am=b10, i=b1, dw/inc=b000, dtt=b10, r=b1, op=b01 */
#define I2C_SLV_DMA_TX_CTRL (0x6000000d) /* am=b01, i=b1, dw/inc=b000, dtt=b01, r=b1, op=b01 */
#define I2C_SLV_DMA_CTRL_SIZE_POS (8)
#define I2C_SLV_DMA_CTRL_XFER_POS (21)
static i2c_info_t i2c_slave_devs[] = {
{ .instID = 0,
.reg_base = AR_IO_I2C_SLV0_CON,
#ifdef IO_I2C_SLV0_DMA_RX
.dmarxchanid = IO_I2C_SLV0_DMA_RX,
#else
.dmarxchanid = DMA_NONE,
#endif
#ifdef IO_I2C_SLV0_DMA_TX
.dmatxchanid = IO_I2C_SLV0_DMA_TX,
#else
.dmatxchanid = DMA_NONE,
#endif
.fifo_depth = IO_I2C_SLV0_FS,
.vector_err = IO_I2C_SLV0_INT_ERR,
.isr_err = i2c_slv0_err_ISR,
.vector_rx_avail = IO_I2C_SLV0_INT_RX_AVAIL,
.isr_rx_avail = i2c_slv0_rx_avail_ISR,
.vector_tx_req = IO_I2C_SLV0_INT_TX_REQ,
.isr_tx_req = i2c_slv0_tx_req_ISR,
.vector_stop_det = IO_I2C_SLV0_INT_STOP_DET,
.isr_stop_det = i2c_slv0_stop_det_ISR,
.vector_restart_det = IO_I2C_SLV0_INT_RESTART_DET,
.vector_rd_req = IO_I2C_SLV0_INT_RD_REQ,
.isr_rd_req = i2c_slv0_rd_req_ISR }
};
#endif
#ifdef I2C_DEV_PRESENT
#define REG_WRITE(reg, x) _sr((unsigned)(x), (unsigned)(dev->reg_base + reg))
#define REG_READ(reg) _lr((unsigned)(dev->reg_base + reg))
#define REG_WRITE_BITS(reg, x, y, len, pos) REG_WRITE(reg, ((((x) & ~((~(0xffffffff << len)) << pos)) \
| (((y) << pos) & ((~(0xffffffff << len)) << pos)))))
/* API functions */
uint32_t io_i2c_slave_open(uint32_t dev_id)
{
i2c_info_pt dev;
uint32_t h = 0;
if ((0 != i2c_handles[0]) || (dev_id != 0)) { /* device still open or non-zero id */
return 1;
}
i2c_handles[0] = &i2c_slave_devs[0];
dev = i2c_handles[0];
/* enable clock; replicate code to make sure i2c enable is 255+ cycles later (see databook) */
for (h = 0; h != 255; h++) {
REG_WRITE(I2C_CLKEN, 0x1);
}
/* mask all interrupts */
REG_WRITE(I2C_INTR_MASK, 0);
/* get stop detect interrupt only when addressed */
REG_WRITE(I2C_CON, (REG_READ(I2C_CON) | (0x1 << 7)));
/* initialize */
dev->handling_tx = dev->handling_rx = 0;
dev->tx_data = dev->rx_data = NULL;
/* set interrupt vector, mid/high priority */
_setvecti(dev->vector_err, dev->isr_err);
_setvecti(dev->vector_rx_avail, dev->isr_rx_avail);
_setvecti(dev->vector_tx_req, dev->isr_tx_req);
_setvecti(dev->vector_stop_det, dev->isr_stop_det);
_setvecti(dev->vector_restart_det, dev->isr_stop_det);
_setvecti(dev->vector_rd_req, dev->isr_rd_req);
#ifdef __Xdmac
dev->dmarxdescriptor = &i2c_dmarx_descriptors[4 * 0];
dev->dmatxdescriptor = &i2c_dmatx_descriptors[8 * 0];
if (dev->dmarxchanid != DMA_NONE) {
dev->dmarxdescriptor[1] = dev->reg_base + I2C_DATA_CMD;
dev->dmarxdescriptor[3] = 0;
_setvecti(DMAC_INT_BASE + dev->dmarxchanid, dev->isr_rx_avail);
_setvecti(DMAC_ERR_BASE + dev->dmarxchanid, dev->isr_err);
}
if (dev->dmatxchanid != DMA_NONE) { /* one descriptor only */
dev->dmatxdescriptor[2] = dev->reg_base + I2C_DATA_CMD;
dev->dmatxdescriptor[3] = 0;
_setvecti(DMAC_INT_BASE + dev->dmatxchanid, dev->isr_tx_req);
_setvecti(DMAC_ERR_BASE + dev->dmatxchanid, dev->isr_err);
}
#endif
/* enable device */
REG_WRITE(I2C_ENABLE, 0x1);
/* unmask interrupt: stop-detect, rd-req, rx-over, tx-abort */
REG_WRITE(I2C_INTR_MASK,
R_STOP_DET | R_RD_REQ | R_RX_OVER | R_TX_ABRT);
return 0;
}
void io_i2c_slave_close(uint32_t dev_id)
{
i2c_info_pt dev = i2c_handles[dev_id];
/* clear all interrupts */
REG_WRITE(I2C_INTR_MASK, 0);
REG_READ(I2C_CLR_INTR);
/* disable */
REG_WRITE(I2C_ENABLE, 0);
/* reset regs */
REG_WRITE(I2C_CON, 0x4);
REG_WRITE(I2C_SAR, 0);
REG_WRITE(I2C_RX_TL, 0);
REG_WRITE(I2C_TX_TL, 0);
REG_WRITE(I2C_SDA_HOLD, 0x1);
REG_WRITE(I2C_SDA_SETUP, 0x64);
REG_WRITE(I2C_FS_SPKLEN, 0x1);
/* gate the I2C clock */
REG_WRITE(I2C_CLKEN, 0);
_setvecti(dev->vector_err, NULL);
_setvecti(dev->vector_rx_avail, NULL);
_setvecti(dev->vector_tx_req, NULL);
_setvecti(dev->vector_stop_det, NULL);
_setvecti(dev->vector_restart_det, NULL);
_setvecti(dev->vector_rd_req, NULL);
#ifdef __Xdmac
if (dev->dmarxchanid != DMA_NONE) {
_setvecti(DMAC_INT_BASE + dev->dmarxchanid, NULL);
_setvecti(DMAC_ERR_BASE + dev->dmarxchanid, NULL);
_dma_chan_reset(0x1 << dev->dmarxchanid);
}
if (dev->dmatxchanid != DMA_NONE) {
_setvecti(DMAC_INT_BASE + dev->dmatxchanid, NULL);
_setvecti(DMAC_ERR_BASE + dev->dmatxchanid, NULL);
_dma_chan_reset(0x1 << dev->dmatxchanid);
}
#endif
dev->rx_cb = NULL;
dev->tx_cb = NULL;
dev->err_cb = NULL;
i2c_handles[dev_id] = 0;
}
void io_i2c_slave_read(uint32_t dev_id, uint8_t *data, uint32_t *size)
{
i2c_info_pt dev = i2c_handles[dev_id];
uint32_t cnt = 0, h = 0, val = 0, avail = 0;
dev->rx_data = data;
dev->rx_size = *size;
dev->rx_count = 0;
dev->p_rxsize = size;
#ifdef __Xdmac
if (dev->dmarxchanid == DMA_NONE) {
#endif
/* mask stop-condition interrupt (to prevent stop-det ISR from interrupting) */
val = REG_READ(I2C_INTR_MASK);
REG_WRITE(I2C_INTR_MASK, (val & ~R_STOP_DET));
if (dev->handling_rx == 0) {
dev->handling_rx = 1;
dev->stop_detected = 0;
/* unmask interrupt: rx threshold (rx-full) */
val = REG_READ(I2C_INTR_MASK) | R_RX_FULL;
REG_WRITE(I2C_INTR_MASK, val);
} else {
/* RX already in progress, due to earlier read() calls */
if (dev->stop_detected == 0) {
/* unmask interrupts: rx threshold (rx-full) and stop-condition */
val = REG_READ(I2C_INTR_MASK) | R_RX_FULL;
REG_WRITE(I2C_INTR_MASK, val);
} else {
/* there is data in the rx-fifo remaining: read it */
cnt = dev->rx_size - dev->rx_count;
avail = REG_READ(I2C_RXFLR);
if (cnt >= avail) { /* after reading, all data processed, rx buffer not completely filled */
cnt = avail;
dev->handling_rx = 0;
}
for (h = 0; h != cnt; h++) {
dev->rx_data[dev->rx_count++] = REG_READ(I2C_DATA_CMD);
}
if (dev->handling_rx == 0) {
if (dev->rx_size != dev->rx_count) { /* read buffer NOT completely filled */
*(dev->p_rxsize) = dev->rx_count;
}
}
/* slave rx done */
dev->rx_data = NULL;
if (NULL != dev->rx_cb) {
dev->rx_cb(dev_id);
}
}
}
/* unmask stop-condition interrupt again */
val = REG_READ(I2C_INTR_MASK) | R_STOP_DET;
REG_WRITE(I2C_INTR_MASK, val);
#ifdef __Xdmac
} else { /* DMA: create descriptor */
uint32_t threshold;
dev->handling_rx = 1;
dev->stop_detected = 0;
if (*size != 0) {
/* rx data available; at least one, more is uncertain */
threshold = REG_READ(I2C_RX_TL);
dev->dmarxdescriptor[0] =
I2C_SLV_DMA_RX_CTRL | ((threshold + 1) <<
I2C_SLV_DMA_CTRL_XFER_POS) | ((*size
-
1) <<
I2C_SLV_DMA_CTRL_SIZE_POS);
dev->dmarxdescriptor[2] = (uint32_t) data + (*size - 1);
/* init dma */
if (dev->dmarxchanid < DMAC_MEM_CHAN_CNT) {
_dma_chan_desc(dev->dmarxchanid,
&(dev->dmarxdescriptor[0]));
} else {
_dma_chan_desc_aux(dev->dmarxchanid,
&(dev->dmarxdescriptor[0]));
}
_dma_chan_enable((0x1 << dev->dmarxchanid), 1);
}
}
#endif
}
void io_i2c_slave_write(uint32_t dev_id, uint8_t *data, uint32_t *size)
{
i2c_info_pt dev = i2c_handles[dev_id];
uint32_t cnt = 0, h = 0, val = 0, free = 0;
dev->tx_data = data;
dev->tx_size = *size;
dev->tx_count = 0;
dev->p_txsize = size;
#ifdef __Xdmac
if (dev->dmatxchanid == DMA_NONE) {
#endif
/* mask read request interrupt (to prevent read request ISR from interrupting) */
val = REG_READ(I2C_INTR_MASK);
REG_WRITE(I2C_INTR_MASK, (val & ~R_RD_REQ));
if (dev->handling_tx == 0) {
dev->handling_tx = 1;
dev->rd_req_detected = 0;
} else {
/* TX already in progress, due to earlier write() calls */
if (dev->rd_req_detected != 0) {
/* there is space in the tx-fifo remaining: fill it */
cnt = dev->tx_size - dev->tx_count;
free = dev->fifo_depth - REG_READ(I2C_TXFLR);
if (cnt > free) {
cnt = free;
}
for (h = 0; h != cnt; h++) {
REG_WRITE(I2C_DATA_CMD,
(dev->tx_data[dev->tx_count++]));
}
if (dev->tx_size == dev->tx_count) { /* write buffer completely emptied */
dev->tx_data = NULL;
if (NULL != dev->tx_cb) {
dev->tx_cb(dev_id);
}
}
/* unmask interrupt: tx-threshold (tx-empty) */
val = REG_READ(I2C_INTR_MASK) | R_TX_EMPTY;
REG_WRITE(I2C_INTR_MASK, val);
}
}
/* unmask rd-req interrupt again */
val = REG_READ(I2C_INTR_MASK) | R_RD_REQ;
REG_WRITE(I2C_INTR_MASK, val);
#ifdef __Xdmac
} else { /* DMA: create descriptor */
uint32_t threshold;
dev->handling_tx = 1;
dev->rd_req_detected = 0;
if (*size != 0) {
/* tx data available; at least one, more is uncertain */
threshold = REG_READ(I2C_TX_TL);
dev->dmatxdescriptor[0] =
I2C_SLV_DMA_TX_CTRL | ((dev->fifo_depth - threshold) <<
I2C_SLV_DMA_CTRL_XFER_POS) | ((*size
-
1) <<
I2C_SLV_DMA_CTRL_SIZE_POS);
dev->dmatxdescriptor[1] = (uint32_t) data + (*size - 1);
/* init dma */
if (dev->dmatxchanid < DMAC_MEM_CHAN_CNT) {
_dma_chan_desc(dev->dmatxchanid,
&(dev->dmatxdescriptor[0]));
} else {
_dma_chan_desc_aux(dev->dmatxchanid,
&(dev->dmatxdescriptor[0]));
}
}
}
#endif
}
void io_i2c_slave_ioctl(uint32_t dev_id, uint32_t cmd, void *arg)
{
i2c_info_pt dev = i2c_handles[dev_id];
uint32_t data = 0, enable = 0;
switch (cmd) {
case IO_SET_CB_RX:
dev->rx_cb = ((io_cb_t *) arg)->cb;
break;
case IO_SET_CB_TX:
dev->tx_cb = ((io_cb_t *) arg)->cb;
break;
case IO_SET_CB_ERR:
dev->err_cb = ((io_cb_t *) arg)->cb;
break;
default:
{
enable = REG_READ(I2C_ENABLE);
REG_WRITE(I2C_ENABLE, (enable & ~(0x1)));
switch (cmd) {
case IO_I2C_SLAVE_SET_HOLD_TIME_RX:
data = REG_READ(I2C_SDA_HOLD);
REG_WRITE_BITS(I2C_SDA_HOLD, data, *((uint32_t *) arg), 8,
16);
break;
case IO_I2C_SLAVE_SET_HOLD_TIME_TX:
data = REG_READ(I2C_SDA_HOLD);
REG_WRITE_BITS(I2C_SDA_HOLD, data, *((uint32_t *) arg), 16,
0);
break;
case IO_I2C_SLAVE_SET_10BIT_ADDR:
data = REG_READ(I2C_CON);
REG_WRITE_BITS(I2C_CON, data, *((uint32_t *) arg), 1, 3);
break;
case IO_I2C_SLAVE_SET_SETUP_TIME:
REG_WRITE(I2C_SDA_SETUP, *((uint32_t *) arg));
break;
case IO_I2C_SLAVE_SET_SPKLEN:
REG_WRITE(I2C_FS_SPKLEN, *((uint32_t *) arg));
break;
case IO_I2C_SLAVE_SET_ADDR:
REG_WRITE(I2C_SAR, *((uint32_t *) arg));
break;
case IO_I2C_SLAVE_SET_RX_THRESHOLD:
REG_WRITE(I2C_RX_TL, *((uint32_t *) arg));
break;
case IO_I2C_SLAVE_SET_TX_THRESHOLD:
REG_WRITE(I2C_TX_TL, *((uint32_t *) arg));
break;
default:
break;
}
while ((0x1 & REG_READ(I2C_ENABLE_STATUS)) != 0) {
;
}
enable = REG_READ(I2C_ENABLE);
REG_WRITE(I2C_ENABLE, (enable | 0x1));
break;
}
}
}
static _Interrupt void i2c_slv0_err_ISR()
{
uint32_t dev_id = 0;
i2c_info_pt dev = i2c_handles[dev_id];
if (REG_READ(I2C_CLR_RX_OVER)) {
if (NULL != dev->err_cb) {
dev->err_cb(0);
}
}
if (REG_READ(I2C_CLR_TX_ABRT)) {
/* must be reception of read command (rd_req) while tx-fifo non-empty: results in flush of fifo */
}
}
static _Interrupt void i2c_slv0_rx_avail_ISR()
{
uint32_t dev_id = 0;
i2c_info_pt dev = i2c_handles[dev_id];
uint32_t cnt = 0, h = 0, val = 0, avail = 0;
#ifdef __Xdmac
if (dev->dmarxchanid == DMA_NONE) {
#endif
/* read data from fifo */
cnt = dev->rx_size - dev->rx_count;
avail = REG_READ(I2C_RXFLR);
if (cnt > avail) {
cnt = avail;
}
for (h = 0; h != cnt; h++) {
dev->rx_data[dev->rx_count++] = REG_READ(I2C_DATA_CMD);
}
if (dev->rx_size == dev->rx_count) { /* read buffer completely filled */
dev->rx_data = NULL;
if (NULL != dev->rx_cb) {
dev->rx_cb(dev_id);
}
/* mask rx-avail interrupt */
val = REG_READ(I2C_INTR_MASK) & ~R_RX_FULL;
REG_WRITE(I2C_INTR_MASK, val);
}
#ifdef __Xdmac
} else {
/* DMA RX xfer done */
_dma_chan_enable((0x1 << dev->dmarxchanid), 0);
_dma_int_clear((0x1 << dev->dmarxchanid));
/* call user callback function, if any */
dev->rx_data = NULL;
if (dev->rx_cb != NULL) {
dev->rx_cb(dev_id);
}
}
#endif
}
static _Interrupt void i2c_slv0_tx_req_ISR()
{
uint32_t dev_id = 0;
i2c_info_pt dev = i2c_handles[dev_id];
uint32_t cnt = 0, h = 0, val = 0, free = 0;
#ifdef __Xdmac
if (dev->dmatxchanid == DMA_NONE) {
#endif
/* write data into fifo */
cnt = dev->tx_size - dev->tx_count;
free = dev->fifo_depth - REG_READ(I2C_TXFLR);
if (cnt > free) {
cnt = free;
}
for (h = 0; h != cnt; h++) {
REG_WRITE(I2C_DATA_CMD, (dev->tx_data[dev->tx_count++]));
}
if (dev->tx_size == dev->tx_count) {
/* write buffer completely emptied */
dev->tx_data = NULL;
if (NULL != dev->tx_cb) {
dev->tx_cb(dev_id);
}
/* mask tx-threshold (tx-empty) */
val = REG_READ(I2C_INTR_MASK) & ~R_TX_EMPTY;
REG_WRITE(I2C_INTR_MASK, val);
}
#ifdef __Xdmac
} else {
/* DMA TX xfer done */
_dma_chan_enable((0x1 << dev->dmatxchanid), 0);
_dma_int_clear((0x1 << dev->dmatxchanid));
/* call user callback function, if any */
dev->tx_data = NULL;
if (dev->tx_cb != NULL) {
dev->tx_cb(dev_id);
}
}
#endif
}
static _Interrupt void i2c_slv0_stop_det_ISR()
{
uint32_t dev_id = 0;
i2c_info_pt dev = i2c_handles[dev_id];
uint32_t cnt = 0, h = 0, val = 0, avail = 0;
if (dev->handling_rx == 1) {
avail = REG_READ(I2C_RXFLR);
if (dev->rx_data == NULL) {
if (avail == 0) { /* all data processed */
dev->handling_rx = 0;
} else { /* still data in fifo to process, new data will not become available anymore */
dev->stop_detected = 1;
}
} else {
#ifdef __Xdmac
if (dev->dmarxchanid != DMA_NONE) { /* disable DMA transfer and determine how much data has been transferred */
uint32_t ctrl;
_dma_chan_enable((0x1 << dev->dmarxchanid), 0);
_dma_chan_desc_get_ctrl(dev->dmarxchanid, &ctrl);
if (dev->dmarxchanid < DMAC_MEM_CHAN_CNT) {
_dma_chan_desc_get_ctrl(dev->dmarxchanid, &ctrl);
} else {
_dma_chan_desc_aux_get_ctrl(dev->dmarxchanid, &ctrl);
}
dev->rx_count =
((dev->rx_size - 1) -
((ctrl >> I2C_SLV_DMA_CTRL_SIZE_POS) & 0x1fff));
}
#endif
/* read remaining data from fifo */
cnt = dev->rx_size - dev->rx_count;
if (cnt < avail) { /* after reading, still data in fifo to process, new data will not become available anymore */
dev->stop_detected = 1;
} else if (cnt == avail) { /* after reading, all data processed */
dev->handling_rx = 0;
} else { /* after reading, all data processed, rx buffer not completely filled */
cnt = avail;
dev->handling_rx = 0;
}
for (h = 0; h != cnt; h++) {
dev->rx_data[dev->rx_count++] = REG_READ(I2C_DATA_CMD);
}
if (dev->handling_rx == 0) {
if (dev->rx_size != dev->rx_count) { /* read buffer NOT completely filled */
*(dev->p_rxsize) = dev->rx_count;
}
}
/* slave rx done */
dev->rx_data = NULL;
if (NULL != dev->rx_cb) {
dev->rx_cb(dev_id);
}
}
/* mask rx-avail interrupt, if not done yet */
val = REG_READ(I2C_INTR_MASK) & ~R_RX_FULL;
REG_WRITE(I2C_INTR_MASK, val);
}
if (dev->handling_tx == 1) {
dev->handling_tx = 0;
if (dev->tx_data != NULL) {
/* slave tx done */
*(dev->p_txsize) = dev->tx_count - REG_READ(I2C_TXFLR);
dev->tx_data = NULL;
if (NULL != dev->rx_cb) {
dev->rx_cb(dev_id);
}
}
}
REG_READ(I2C_CLR_STOP_DET);
}
static _Interrupt void i2c_slv0_rd_req_ISR()
{
uint32_t dev_id = 0;
i2c_info_pt dev = i2c_handles[dev_id];
uint32_t cnt = 0, h = 0, val = 0;
if (dev->tx_data != NULL) {
dev->rd_req_detected = 1;
#ifdef __Xdmac
if (dev->dmatxchanid == DMA_NONE) {
#endif
/* write data into (empty) fifo */
cnt = dev->tx_size - dev->tx_count;
if (cnt > dev->fifo_depth) {
cnt = dev->fifo_depth;
}
for (h = 0; h != cnt; h++) {
REG_WRITE(I2C_DATA_CMD, (dev->tx_data[dev->tx_count++]));
}
if (dev->tx_size == dev->tx_count) { /* write buffer completely emptied */
dev->tx_data = NULL;
if (NULL != dev->tx_cb) {
dev->tx_cb(dev_id);
}
} else {
/* unmask interrupts: tx-threshold (tx-empty) */
val = REG_READ(I2C_INTR_MASK) | R_TX_EMPTY;
REG_WRITE(I2C_INTR_MASK, val);
}
#ifdef __Xdmac
} else { /* have DMAC fill the fifo */
_dma_chan_enable((0x1 << dev->dmatxchanid), 1);
}
#endif
} else {
/* no data available for tx --> the only thing to do is returning any data */
REG_WRITE(I2C_DATA_CMD, 0xff);
}
REG_READ(I2C_CLR_RD_REQ);
}
#endif

View File

@@ -1,491 +0,0 @@
/* ------------------------------------------
* Copyright (c) 2018, 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.
*
--------------------------------------------- */
#include "embARC_error.h"
#include "embARC_toolchain.h"
#include "arc/arc_exception.h"
#include "device/subsystem/i2c_master.h"
#include "device/subsystem/ss_i2c_master.h"
#include "device/subsystem/i2c_priv.h"
#define REG_READ(x) arc_aux_read((ctx->reg_base + x))
#define REG_WRITE(x, y) arc_aux_write((ctx->reg_base + x), y)
/**
* @fn int32_t ss_iic_master_putready(SS_IIC_MASTER_DEV_CONTEXT *ctx)
* @brief Test whether iic is ready to write, 1 ready, 0 not ready
*/
Inline int32_t ss_iic_master_putready(SS_IIC_MASTER_DEV_CONTEXT *ctx)
{
uint32_t status = REG_READ(I2C_STATUS);
return ((status & IC_STATUS_TFNF) != 0);
}
/**
* @fn int32_t ss_iic_master_getready(SS_IIC_MASTER_DEV_CONTEXT *ctx)
* @brief test whether iic is ready to receive, 1 ready, 0 not ready
*/
Inline int32_t ss_iic_master_getready(SS_IIC_MASTER_DEV_CONTEXT *ctx)
{
uint32_t status = REG_READ(I2C_STATUS);
return ((status & IC_STATUS_RFNE) != 0);
}
/**
* @fn void ss_iic_mask_interrupt(SS_IIC_MASTER_DEV_CONTEXT *ctx, uint32_t mask)
* @brief Mask iic interrupt
*/
Inline void ss_iic_mask_interrupt(SS_IIC_MASTER_DEV_CONTEXT *ctx, uint32_t mask)
{
uint32_t intr_mask = REG_READ(I2C_INTR_MASK);
REG_WRITE(I2C_INTR_MASK, intr_mask & (~mask));
}
static void ss_iic_master_enable_device(SS_IIC_MASTER_DEV_CONTEXT *ctx)
{
DEV_IIC_INFO *info = ctx->info;
uint32_t enable = REG_READ(I2C_ENABLE);
if (((enable & 0x1) & DEV_ENABLED) == 0) {
REG_WRITE(I2C_ENABLE, (enable | 0x1));
info->status |= DEV_ENABLED;
}
}
static void ss_iic_master_disable_device(SS_IIC_MASTER_DEV_CONTEXT *ctx)
{
uint32_t enable = REG_READ(I2C_ENABLE);
REG_WRITE(I2C_ENABLE, (enable & (~(0x1))));
while ((0x1 & REG_READ(I2C_ENABLE_STATUS)) != 0) {
;
}
}
/* reset IIC master */
static void ss_iic_master_reset_device(SS_IIC_MASTER_DEV_CONTEXT *ctx)
{
DEV_IIC_INFO *info = ctx->info;
io_i2c_master_close(ctx->dev_id);
info->next_cond = IIC_MODE_STOP;
info->cur_state = IIC_FREE;
info->err_state = IIC_ERR_NONE;
ctx->flags = 0;
io_i2c_master_open(ctx->dev_id);
}
/** disable iic master interrupt for transmit or receive */
static void ss_iic_master_dis_cbr(SS_IIC_MASTER_DEV_CONTEXT *ctx, uint32_t cbrtn)
{
switch (cbrtn) {
case SS_IIC_MASTER_RDY_SND:
ss_iic_mask_interrupt(ctx, R_TX_EMPTY);
break;
case SS_IIC_MASTER_RDY_RCV:
ss_iic_mask_interrupt(ctx, R_TX_EMPTY | R_RX_FULL);
break;
default:
break;
}
}
/**
* @fn void ss_iic_master_flush_tx(SS_IIC_MASTER_DEV_CONTEXT *ctx)
* @brief flush TX FIFO
*/
Inline void ss_iic_master_flush_tx(SS_IIC_MASTER_DEV_CONTEXT *ctx)
{
}
/**
* @fn int32_t ss_iic_master_flush_rx(SS_IIC_MASTER_DEV_CONTEXT *ctx)
* @brief Flush RX FIFO
*/
Inline void ss_iic_master_flush_rx(SS_IIC_MASTER_DEV_CONTEXT *ctx)
{
}
/**
* @fn uint32_t ss_iic_master_get_txavail(SS_IIC_MASTER_DEV_CONTEXT *ctx)
* @brief Get available transmit FIFO count
*/
Inline uint32_t ss_iic_master_get_txavail(SS_IIC_MASTER_DEV_CONTEXT *ctx)
{
uint32_t flr = REG_READ(I2C_TXFLR);
return (int32_t)(IC_TX_RX_FIFO_SIZE - flr);
}
/**
* @fn ss_iic_master_get_rxavail(SS_IIC_MASTER_DEV_CONTEXT *ctx)
* @brief Get available receive FIFO count
*/
Inline uint32_t ss_iic_master_get_rxavail(SS_IIC_MASTER_DEV_CONTEXT *ctx)
{
uint32_t flr = REG_READ(I2C_RXFLR);
return (int32_t)flr;
}
int32_t ss_iic_master_close(SS_IIC_MASTER_DEV_CONTEXT *ctx)
{
int32_t ret = E_OK;
DEV_IIC_INFO *info = ctx->info;
if (info->opn_cnt > 0) {
info->opn_cnt = 0;
io_i2c_master_close(ctx->dev_id);
int_disable(ctx->int_err);
int_disable(ctx->int_rx_avail);
int_disable(ctx->int_tx_req);
int_disable(ctx->int_stop_det);
} else {
ret = E_CLSED;
}
return ret;
}
int32_t ss_iic_master_control(SS_IIC_MASTER_DEV_CONTEXT *ctx, uint32_t ctrl_cmd, void *param)
{
int32_t ercd = E_OK;
uint32_t val32;
uint32_t arg;
uint32_t dev_id = ctx->dev_id;
DEV_IIC_INFO *iic_info_ptr = ctx->info;
io_cb_t callback;
switch (ctrl_cmd) {
case IIC_CMD_GET_STATUS:
SS_IIC_MASTER_CHECK_EXP((param != NULL) && CHECK_ALIGN_4BYTES(param), E_PAR);
*((int32_t *)param) = iic_info_ptr->status;
break;
case IIC_CMD_ENA_DEV:
ss_iic_master_enable_device(ctx);
break;
case IIC_CMD_DIS_DEV:
ss_iic_master_disable_device(ctx);
break;
case IIC_CMD_RESET:
ss_iic_master_reset_device(ctx);
break;
case IIC_CMD_FLUSH_TX:
ss_iic_master_flush_tx(ctx);
break;
case IIC_CMD_FLUSH_RX:
ss_iic_master_flush_rx(ctx);
break;
case IIC_CMD_SET_ADDR_MODE:
val32 = (uint32_t)param;
SS_IIC_MASTER_CHECK_EXP((val32 == IIC_7BIT_ADDRESS) || (val32 == IIC_10BIT_ADDRESS), E_PAR);
if (val32 == IIC_10BIT_ADDRESS) {
arg = 1;
io_i2c_master_ioctl(dev_id, IO_I2C_MASTER_SET_10BIT_ADDR, &arg);
iic_info_ptr->addr_mode = IIC_10BIT_ADDRESS;
} else {
arg = 0;
io_i2c_master_ioctl(dev_id, IO_I2C_MASTER_SET_10BIT_ADDR, &arg);
iic_info_ptr->addr_mode = IIC_7BIT_ADDRESS;
}
iic_info_ptr->addr_mode = val32;
break;
case IIC_CMD_GET_RXAVAIL:
SS_IIC_MASTER_CHECK_EXP((param != NULL) && CHECK_ALIGN_4BYTES(param), E_PAR);
*((int32_t *)param) = ss_iic_master_get_rxavail(ctx);
break;
case IIC_CMD_GET_TXAVAIL:
SS_IIC_MASTER_CHECK_EXP((param != NULL) && CHECK_ALIGN_4BYTES(param), E_PAR);
*((int32_t *)param) = ss_iic_master_get_txavail(ctx);
break;
case IIC_CMD_SET_TXCB:
SS_IIC_MASTER_CHECK_EXP(CHECK_ALIGN_4BYTES(param), E_PAR);
callback.cb = param;
io_i2c_master_ioctl(dev_id, IO_SET_CB_TX, &callback);
break;
case IIC_CMD_SET_RXCB:
SS_IIC_MASTER_CHECK_EXP(CHECK_ALIGN_4BYTES(param), E_PAR);
callback.cb = param;
io_i2c_master_ioctl(dev_id, IO_SET_CB_RX, &callback);
break;
case IIC_CMD_SET_ERRCB:
SS_IIC_MASTER_CHECK_EXP(CHECK_ALIGN_4BYTES(param), E_PAR);
callback.cb = param;
io_i2c_master_ioctl(dev_id, IO_SET_CB_ERR, &callback);
break;
case IIC_CMD_ABORT_TX:
ercd = E_NOSPT;
break;
case IIC_CMD_ABORT_RX:
ercd = E_NOSPT;
break;
case IIC_CMD_SET_TXINT:
val32 = (uint32_t)param;
if (val32 == 0) {
ss_iic_master_dis_cbr(ctx, SS_IIC_MASTER_RDY_SND);
} else {
ss_iic_master_dis_cbr(ctx, SS_IIC_MASTER_RDY_SND);
}
break;
case IIC_CMD_SET_RXINT:
val32 = (uint32_t)param;
if (val32 == 0) {
ss_iic_master_dis_cbr(ctx, SS_IIC_MASTER_RDY_RCV);
} else {
ss_iic_master_dis_cbr(ctx, SS_IIC_MASTER_RDY_RCV);
}
break;
case IIC_CMD_SET_TXINT_BUF:
ercd = E_NOSPT;
break;
case IIC_CMD_SET_RXINT_BUF:
ercd = E_NOSPT;
break;
case IIC_CMD_MST_SET_SPEED_MODE:
val32 = (uint32_t)param;
SS_IIC_MASTER_CHECK_EXP((val32 >= IIC_SPEED_STANDARD) && (val32 <= IIC_SPEED_FAST), E_PAR);
if (val32 == IIC_SPEED_STANDARD) {
arg = 1;
io_i2c_master_ioctl(dev_id, IO_I2C_MASTER_SET_SPEED, &arg);
iic_info_ptr->speed_mode = IIC_SPEED_STANDARD;
} else {
arg = 2;
io_i2c_master_ioctl(dev_id, IO_I2C_MASTER_SET_SPEED, &arg);
iic_info_ptr->speed_mode = IIC_SPEED_FAST;
}
break;
case IIC_CMD_MST_SET_TAR_ADDR:
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) {
arg = val32;
io_i2c_master_ioctl(dev_id, IO_I2C_MASTER_SET_TARGET_ADDR, &arg);
iic_info_ptr->tar_addr = val32;
}
break;
case IIC_CMD_MST_SET_NEXT_COND:
val32 = (uint32_t) param;
if (val32 == IIC_MODE_STOP) {
arg = I2C_STOP_CMD;
} else if (val32 == IIC_MODE_RESTART) {
arg = I2C_RESTART_CMD;
} else {
arg = 0;
}
io_i2c_master_ioctl(dev_id, IO_I2C_MASTER_SET_NEXT_COND, &arg);
break;
default:
ercd = E_NOSPT;
break;
}
error_exit:
return ercd;
}
/* param: speed mode, 1-standard mode, 2-fast mode, 2 as default in hardware */
int32_t ss_iic_master_open(SS_IIC_MASTER_DEV_CONTEXT *ctx, uint32_t param)
{
int32_t ercd = E_OK;
uint32_t dev_id = ctx->dev_id;
DEV_IIC_INFO *info = ctx->info;
io_cb_t callback;
int32_t int_e = 0;
uint32_t arg;
SS_IIC_MASTER_CHECK_EXP((param >= IIC_SPEED_STANDARD) && (param <= IIC_SPEED_FAST), E_PAR);
if (info->opn_cnt == 0) {
SS_IIC_MASTER_CHECK_EXP(io_i2c_master_open(dev_id) == 0, E_SYS);
if (param == IIC_SPEED_STANDARD) {
arg = 1;
io_i2c_master_ioctl(dev_id, IO_I2C_MASTER_SET_SPEED, &arg);
info->speed_mode = IIC_SPEED_STANDARD;
} else {
arg = 2;
io_i2c_master_ioctl(dev_id, IO_I2C_MASTER_SET_SPEED, &arg);
info->speed_mode = IIC_SPEED_FAST;
}
callback.cb = (IO_CB_FUNC)ctx->int_rx_cb;
io_i2c_master_ioctl(dev_id, IO_SET_CB_RX, &callback);
callback.cb = (IO_CB_FUNC)ctx->int_tx_cb;
io_i2c_master_ioctl(dev_id, IO_SET_CB_TX, &callback);
callback.cb = (IO_CB_FUNC)ctx->int_err_cb;
io_i2c_master_ioctl(dev_id, IO_SET_CB_ERR, &callback);
info->opn_cnt++;
info->addr_mode = IIC_7BIT_ADDRESS;
info->mode = DEV_MASTER_MODE;
info->tar_addr &= IIC_7BIT_ADDRESS_MASK;
ctx->flags = 0;
/* enable interrupt */
int_e = int_e | int_enable(ctx->int_err);
int_e = int_e | int_enable(ctx->int_rx_avail);
int_e = int_e | int_enable(ctx->int_tx_req);
int_e = int_e | int_enable(ctx->int_stop_det);
if (int_e != 0) {
ercd = E_PAR;
}
} else {
ercd = E_OPNED;
}
error_exit:
return ercd;
}
int32_t ss_iic_master_write(SS_IIC_MASTER_DEV_CONTEXT *ctx, const void *data, uint32_t len)
{
uint32_t xlen;
uint32_t dev_id = ctx->dev_id;
if (ctx->flags) {
return E_NORES;
}
if (arc_locked()) {
/*
* not allow to be called in isr or cpu is locked.
* because the bottom driver is simply interrupt driven
*/
return E_SYS;
}
xlen = len;
ctx->flags = SS_IIC_MASTER_FLAG_TX;
io_i2c_master_write(dev_id, (uint8_t *)data, &xlen);
/* wait finished: i2c master int enable & no cpu lock */
while (ctx->flags & SS_IIC_MASTER_FLAG_TX) {
;
}
if (ctx->flags & SS_IIC_MASTER_FLAG_ERROR) {
ctx->flags = 0;
return E_SYS;
}
ctx->flags = 0;
return len;
}
int32_t ss_iic_master_read(SS_IIC_MASTER_DEV_CONTEXT *ctx, const void *data, uint32_t len)
{
uint32_t xlen;
uint32_t dev_id = ctx->dev_id;
if (ctx->flags) {
return E_NORES;
}
if (arc_locked()) {
/*
* not allow to be called in isr or cpu is locked.
* because the bottom driver is simply interrupt driven
*/
return E_SYS;
}
xlen = len;
ctx->flags = SS_IIC_MASTER_FLAG_RX;
io_i2c_master_read(dev_id, (uint8_t *)data, &xlen);
/* wait finished: i2c master int enable & no cpu lock */
while (ctx->flags & SS_IIC_MASTER_FLAG_RX) {
;
}
if (ctx->flags & SS_IIC_MASTER_FLAG_ERROR) {
ctx->flags = 0;
return E_SYS;
}
ctx->flags = 0;
return len;
}
void ss_iic_master_tx_cb(SS_IIC_MASTER_DEV_CONTEXT *ctx, void *param)
{
DEV_IIC_INFO *info = ctx->info;
if (ctx->flags & SS_IIC_MASTER_FLAG_TX) {
ctx->flags &= ~SS_IIC_MASTER_FLAG_TX;
if (info->iic_cbs.tx_cb) {
info->iic_cbs.tx_cb(info);
}
}
}
void ss_iic_master_rx_cb(SS_IIC_MASTER_DEV_CONTEXT *ctx, void *param)
{
DEV_IIC_INFO *info = ctx->info;
if (ctx->flags & SS_IIC_MASTER_FLAG_RX) {
ctx->flags &= ~SS_IIC_MASTER_FLAG_RX;
if (info->iic_cbs.rx_cb) {
info->iic_cbs.rx_cb(info);
}
}
}
void ss_iic_master_err_cb(SS_IIC_MASTER_DEV_CONTEXT *ctx, void *param)
{
DEV_IIC_INFO *info = ctx->info;
ctx->flags |= SS_IIC_MASTER_FLAG_ERROR;
if (info->iic_cbs.err_cb) {
info->iic_cbs.err_cb(info);
}
}

View File

@@ -1,949 +0,0 @@
/* ==========================================================================
* Synopsys DesignWare Sensor and Control IP Subsystem IO Software Driver and
* documentation (hereinafter, "Software") is an Unsupported proprietary work
* of Synopsys, Inc. unless otherwise expressly agreed to in writing between
* Synopsys and you.
*
* The Software IS NOT an item of Licensed Software or Licensed Product under
* any End User Software License Agreement or Agreement for Licensed Product
* with Synopsys or any supplement thereto. You are permitted to use and
* redistribute this Software in source and binary forms, with or without
* modification, provided that redistributions of source code must retain this
* notice. You may not view, use, disclose, copy or distribute this file or
* any information contained herein except pursuant to this license grant from
* Synopsys. If you do not agree with this notice, including the disclaimer
* below, then you are not authorized to use the Software.
*
* THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS 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.
* ========================================================================== */
/*==========================================================================
* Library DW_DFSS-1.1.6
* ========================================================================== */
#include <stdlib.h>
#include <stddef.h>
#include <stdint.h>
#include "device/subsystem/spi_slave.h"
#include "device/subsystem/spi_priv.h"
#include "io_config.h"
#include "apexextensions.h"
/* local defines (!!) */
#define SPI_TRANSMIT_RECEIVE_MODE (0)
#define SPI_TRANSMIT_ONLY_MODE (1)
#define SPI_RECEIVE_ONLY_MODE (2)
#ifdef IO_SPI_SLV0_PRESENT
#define SPI_DEV_PRESENT
#endif
#ifdef IO_SPI_SLV1_PRESENT
#define SPI_DEV_PRESENT
#endif
#ifdef IO_SPI_SLV2_PRESENT
#define SPI_DEV_PRESENT
#endif
#ifdef IO_SPI_SLV3_PRESENT
#define SPI_DEV_PRESENT
#endif
#ifdef SPI_DEV_PRESENT
#define SPI_MAX_CNT (4)
static void spi_slv_rx_ISR_proc(uint32_t dev_id);
static void spi_slv_tx_ISR_proc(uint32_t dev_id);
static void spi_slv_idle_ISR_proc(uint32_t dev_id);
static void spi_slv_err_ISR_proc(uint32_t dev_id);
#ifdef IO_SPI_SLV0_PRESENT
static _Interrupt void spi_slv0_rx_ISR()
{
spi_slv_rx_ISR_proc(0);
}
static _Interrupt void spi_slv0_tx_ISR()
{
spi_slv_tx_ISR_proc(0);
}
static _Interrupt void spi_slv0_idle_ISR()
{
spi_slv_idle_ISR_proc(0);
}
static _Interrupt void spi_slv0_err_ISR()
{
spi_slv_err_ISR_proc(0);
}
#endif
#ifdef IO_SPI_SLV1_PRESENT
static _Interrupt void spi_slv1_rx_ISR()
{
spi_slv_rx_ISR_proc(1);
}
static _Interrupt void spi_slv1_tx_ISR()
{
spi_slv_tx_ISR_proc(1);
}
static _Interrupt void spi_slv1_idle_ISR()
{
spi_slv_idle_ISR_proc(1);
}
static _Interrupt void spi_slv1_err_ISR()
{
spi_slv_err_ISR_proc(1);
}
#endif
#ifdef IO_SPI_SLV2_PRESENT
static _Interrupt void spi_slv2_rx_ISR()
{
spi_slv_rx_ISR_proc(2);
}
static _Interrupt void spi_slv2_tx_ISR()
{
spi_slv_tx_ISR_proc(2);
}
static _Interrupt void spi_slv2_idle_ISR()
{
spi_slv_idle_ISR_proc(2);
}
static _Interrupt void spi_slv2_err_ISR()
{
spi_slv_err_ISR_proc(2);
}
#endif
#ifdef IO_SPI_SLV3_PRESENT
static _Interrupt void spi_slv3_rx_ISR()
{
spi_slv_rx_ISR_proc(3);
}
static _Interrupt void spi_slv3_tx_ISR()
{
spi_slv_tx_ISR_proc(3);
}
static _Interrupt void spi_slv3_idle_ISR()
{
spi_slv_idle_ISR_proc(3);
}
static _Interrupt void spi_slv3_err_ISR()
{
spi_slv_err_ISR_proc(3);
}
#endif
static void fill_txfifo(spi_info_pt dev);
static void retrieve_rxfifo(spi_info_pt dev);
#ifdef __Xdmac
static void create_dma_descriptors_rx(spi_info_pt dev, uint8_t *dest,
uint32_t size, uint32_t burst);
static void create_dma_descriptors_tx(spi_info_pt dev, uint8_t *src,
uint32_t size, uint32_t burst);
#endif
/* SPI slave devices private data structures */
static spi_info_pt spi_handles[SPI_MAX_CNT] = { 0 };
#ifdef __Xdmac
static _Uncached uint32_t spi_dmarx_descriptors[8 * SPI_MAX_CNT];
static _Uncached uint32_t spi_dmatx_descriptors[8 * SPI_MAX_CNT];
#endif
static spi_info_t spi_slave_devs[] = {
#ifdef IO_SPI_SLV0_PRESENT
{ .instID = 0,
.reg_base = AR_IO_SPI_SLV0_CTRLR0,
#ifdef IO_SPI_SLV0_DMA_RX
.dmarxchanid = IO_SPI_SLV0_DMA_RX,
#else
.dmarxchanid = DMA_NONE,
#endif
#ifdef IO_SPI_SLV0_DMA_TX
.dmatxchanid = IO_SPI_SLV0_DMA_TX,
#else
.dmatxchanid = DMA_NONE,
#endif
.rx_vector = IO_SPI_SLV0_INT_RX_AVAIL,
.tx_vector = IO_SPI_SLV0_INT_TX_REQ,
.idle_vector = IO_SPI_SLV0_INT_IDLE,
.err_vector = IO_SPI_SLV0_INT_ERR,
.rx_isr = spi_slv0_rx_ISR,
.tx_isr = spi_slv0_tx_ISR,
.idle_isr = spi_slv0_idle_ISR,
.err_isr = spi_slv0_err_ISR,
.log_xfer_size = (IO_SPI_SLV0_MAX_XFER_SIZE >> 4),
.max_xfer_size = (IO_SPI_SLV0_MAX_XFER_SIZE),
.fifo_depth = IO_SPI_SLV0_FS },
#endif
#ifdef IO_SPI_SLV1_PRESENT
{ .instID = 1,
.reg_base = AR_IO_SPI_SLV1_CTRLR0,
#ifdef IO_SPI_SLV1_DMA_RX
.dmarxchanid = IO_SPI_SLV1_DMA_RX,
#else
.dmarxchanid = DMA_NONE,
#endif
#ifdef IO_SPI_SLV1_DMA_TX
.dmatxchanid = IO_SPI_SLV1_DMA_TX,
#else
.dmatxchanid = DMA_NONE,
#endif
.rx_vector = IO_SPI_SLV1_INT_RX_AVAIL,
.tx_vector = IO_SPI_SLV1_INT_TX_REQ,
.idle_vector = IO_SPI_SLV1_INT_IDLE,
.err_vector = IO_SPI_SLV1_INT_ERR,
.rx_isr = spi_slv1_rx_ISR,
.tx_isr = spi_slv1_tx_ISR,
.idle_isr = spi_slv1_idle_ISR,
.err_isr = spi_slv1_err_ISR,
.log_xfer_size = (IO_SPI_SLV1_MAX_XFER_SIZE >> 4),
.max_xfer_size = (IO_SPI_SLV1_MAX_XFER_SIZE),
.fifo_depth = IO_SPI_SLV1_FS },
#endif
#ifdef IO_SPI_SLV2_PRESENT
{ .instID = 2,
.reg_base = AR_IO_SPI_SLV2_CTRLR0,
#ifdef IO_SPI_SLV2_DMA_RX
.dmarxchanid = IO_SPI_SLV2_DMA_RX,
#else
.dmarxchanid = DMA_NONE,
#endif
#ifdef IO_SPI_SLV2_DMA_TX
.dmatxchanid = IO_SPI_SLV2_DMA_TX,
#else
.dmatxchanid = DMA_NONE,
#endif
.rx_vector = IO_SPI_SLV2_INT_RX_AVAIL,
.tx_vector = IO_SPI_SLV2_INT_TX_REQ,
.idle_vector = IO_SPI_SLV2_INT_IDLE,
.err_vector = IO_SPI_SLV2_INT_ERR,
.rx_isr = spi_slv2_rx_ISR,
.tx_isr = spi_slv2_tx_ISR,
.idle_isr = spi_slv2_idle_ISR,
.err_isr = spi_slv2_err_ISR,
.log_xfer_size = (IO_SPI_SLV2_MAX_XFER_SIZE >> 4),
.max_xfer_size = (IO_SPI_SLV2_MAX_XFER_SIZE),
.fifo_depth = IO_SPI_SLV2_FS },
#endif
#ifdef IO_SPI_SLV3_PRESENT
{ .instID = 3,
.reg_base = AR_IO_SPI_SLV3_CTRLR0,
#ifdef IO_SPI_SLV3_DMA_RX
.dmarxchanid = IO_SPI_SLV3_DMA_RX,
#else
.dmarxchanid = DMA_NONE,
#endif
#ifdef IO_SPI_SLV3_DMA_TX
.dmatxchanid = IO_SPI_SLV3_DMA_TX,
#else
.dmatxchanid = DMA_NONE,
#endif
.rx_vector = IO_SPI_SLV3_INT_RX_AVAIL,
.tx_vector = IO_SPI_SLV3_INT_TX_REQ,
.idle_vector = IO_SPI_SLV3_INT_IDLE,
.err_vector = IO_SPI_SLV3_INT_ERR,
.rx_isr = spi_slv3_rx_ISR,
.tx_isr = spi_slv3_tx_ISR,
.idle_isr = spi_slv3_idle_ISR,
.err_isr = spi_slv3_err_ISR,
.log_xfer_size = (IO_SPI_SLV3_MAX_XFER_SIZE >> 4),
.max_xfer_size = (IO_SPI_SLV3_MAX_XFER_SIZE),
.fifo_depth = IO_SPI_SLV3_FS },
#endif
{ .instID = SPI_MAX_CNT }
};
#define REG_WRITE(reg, x) _sr((unsigned)(x), (unsigned)(dev->reg_base + reg))
#define REG_READ(reg) _lr((unsigned)(dev->reg_base + reg))
#define REG_WRITE_BITS(reg, x, y, len, pos) REG_WRITE(reg, ((((x) & ~((~(0xffffffff << len)) << pos)) \
| (((y) << pos) & ((~(0xffffffff << len)) << pos)))))
#define REG_GET_BITS(reg, len, pos) ((REG_READ(reg) >> pos) & ~(0xffffffff << len))
uint32_t io_spi_slave_open(uint32_t dev_id)
{
uint32_t h = 0;
spi_info_pt dev;
h = 0;
while ((spi_slave_devs[h].instID != dev_id)
&& (spi_slave_devs[h].instID != SPI_MAX_CNT)) {
h++;
}
if ((spi_slave_devs[h].instID == SPI_MAX_CNT) || (0 != spi_handles[dev_id])) { /* dev_id not part of design, or still open */
return 1;
}
spi_handles[dev_id] = &spi_slave_devs[h];
dev = spi_handles[dev_id];
/* enable clock */
REG_WRITE(CLK_ENA, 0x1);
if (dev->max_xfer_size == 16) { /* 16-bits SPI; log_xfer_size == 1 */
dev->log_xfer_size = dev->max_xfer_size >> 4;
REG_WRITE_BITS(CTRL0, 0x0, 15, 4, 0);
} else {
/* 32-bits SPI; log_xfer_size == 2 */
dev->log_xfer_size = dev->max_xfer_size >> 4;
REG_WRITE_BITS(CTRL0, 0x0, 31, 5, 16);
}
/* mask RX-available and TX-empty interrupts, always mask TX-underflow */
REG_WRITE(IMR, ~(R_TX_EMPTY | R_RX_FULL | R_TX_UNDER));
dev->handling_rx = dev->handling_tx = 0;
_setvecti(dev->rx_vector, dev->rx_isr);
_setvecti(dev->tx_vector, dev->tx_isr);
_setvecti(dev->idle_vector, dev->idle_isr);
_setvecti(dev->err_vector, dev->err_isr);
#ifdef __Xdmac
dev->dmarxdescriptor = &spi_dmarx_descriptors[8 * h];
dev->dmatxdescriptor = &spi_dmatx_descriptors[8 * h];
if (dev->dmarxchanid != DMA_NONE) {
dev->dmarxdescriptor[1] = dev->dmarxdescriptor[5] =
dev->reg_base + DR;
dev->dmarxdescriptor[3] = (uint32_t) &(dev->dmarxdescriptor[4]);
dev->dmarxdescriptor[7] = 0;
_setvecti(DMAC_INT_BASE + dev->dmarxchanid, dev->rx_isr);
_setvecti(DMAC_ERR_BASE + dev->dmarxchanid, dev->err_isr);
}
if (dev->dmatxchanid != DMA_NONE) {
dev->dmatxdescriptor[2] = dev->dmatxdescriptor[6] =
dev->reg_base + DR;
dev->dmatxdescriptor[3] = (uint32_t) &(dev->dmatxdescriptor[4]);
dev->dmatxdescriptor[7] = 0;
_setvecti(DMAC_INT_BASE + dev->dmatxchanid, dev->tx_isr);
_setvecti(DMAC_ERR_BASE + dev->dmatxchanid, dev->err_isr);
}
#endif
REG_WRITE(SPIEN, 0x1);
return 0;
}
void io_spi_slave_close(uint32_t dev_id)
{
spi_info_pt dev = spi_handles[dev_id];
REG_WRITE(IMR, 0);
REG_WRITE(SPIEN, 0);
REG_WRITE(CTRL0, 0x7);
REG_WRITE(TXFTLR, 0);
REG_WRITE(RXFTLR, 0);
REG_WRITE(IMR, 0xff);
/* gate clock */
REG_WRITE(CLK_ENA, 0);
_setvecti(dev->rx_vector, NULL);
_setvecti(dev->tx_vector, NULL);
_setvecti(dev->idle_vector, NULL);
_setvecti(dev->err_vector, NULL);
#ifdef __Xdmac
if (dev->dmarxchanid != DMA_NONE) {
_setvecti(DMAC_INT_BASE + dev->dmarxchanid, NULL);
_setvecti(DMAC_ERR_BASE + dev->dmarxchanid, NULL);
_dma_chan_reset(0x1 << dev->dmarxchanid);
}
if (dev->dmatxchanid != DMA_NONE) {
_setvecti(DMAC_INT_BASE + dev->dmatxchanid, NULL);
_setvecti(DMAC_ERR_BASE + dev->dmatxchanid, NULL);
_dma_chan_reset(0x1 << dev->dmatxchanid);
}
#endif
dev->rx_cb = NULL;
dev->tx_cb = NULL;
dev->err_cb = NULL;
spi_handles[dev_id] = 0;
}
void io_spi_slave_read(uint32_t dev_id, uint8_t *data, uint32_t *size)
{
spi_info_pt dev = spi_handles[dev_id];
uint32_t val = 0;
dev->rx_size = *size;
dev->p_rxsize = size;
dev->rx_count = 0;
dev->rx_buff = (void *) data;
dev->handling_rx = 1;
#ifdef __Xdmac
if (dev->dmarxchanid == DMA_NONE) {
#endif
/* Enable RX-available and Idle interrupt */
val = REG_READ(IMR);
REG_WRITE(IMR, (val | R_RX_FULL | R_IDLE));
#ifdef __Xdmac
} else { /* RX descriptor */
if (*size != 0) {
/* rx data available; at least one */
create_dma_descriptors_rx(dev, data, *size,
(1 + REG_READ(RXFTLR)));
/* init dma */
if (dev->dmarxchanid < DMAC_MEM_CHAN_CNT) {
_dma_chan_desc(dev->dmarxchanid,
&(dev->dmarxdescriptor[0]));
} else {
_dma_chan_desc_aux(dev->dmarxchanid,
&(dev->dmarxdescriptor[0]));
}
_dma_chan_enable((0x1 << dev->dmarxchanid), 1);
/* enable the Idle interrupt */
val = REG_READ(IMR);
REG_WRITE(IMR, val | R_IDLE);
}
}
#endif
}
void io_spi_slave_write(uint32_t dev_id, uint8_t *data, uint32_t *size)
{
spi_info_pt dev = spi_handles[dev_id];
uint32_t val = 0;
dev->tx_size = *size;
dev->tx_count = 0;
dev->tx_buff = (void *) data;
dev->handling_tx = 1;
#ifdef __Xdmac
if (dev->dmatxchanid == DMA_NONE) {
#endif
/* write first bytes to fifo, assuming size > 0 */
fill_txfifo(dev);
/* Enable TX-empty, Idle interrupt, and (optional) RX-available */
if (REG_GET_BITS(CTRL0, 2, 8) == SPI_TRANSMIT_ONLY_MODE) {
val = REG_READ(IMR);
REG_WRITE(IMR, (val | R_TX_EMPTY | R_IDLE));
} else { /* TX-RX mode */
val = REG_READ(IMR);
REG_WRITE(IMR, (val | R_TX_EMPTY | R_IDLE | R_RX_FULL));
}
#ifdef __Xdmac
} else { /* TX descriptor */
if (*size != 0) {
/* tx data available; at least one, more is uncertain */
create_dma_descriptors_tx(dev, data, *size,
(dev->fifo_depth -
REG_READ(TXFTLR)));
/* init dma */
if (dev->dmatxchanid < DMAC_MEM_CHAN_CNT) {
_dma_chan_desc(dev->dmatxchanid,
&(dev->dmatxdescriptor[0]));
} else {
_dma_chan_desc_aux(dev->dmatxchanid,
&(dev->dmatxdescriptor[0]));
}
_dma_chan_enable((0x1 << dev->dmatxchanid), 1);
/* enable the Idle interrupt */
val = REG_READ(IMR);
REG_WRITE(IMR, val | R_IDLE);
}
}
#endif
}
void io_spi_slave_ioctl(uint32_t dev_id, uint32_t cmd, void *arg)
{
spi_info_pt dev = spi_handles[dev_id];
uint32_t regval;
switch (cmd) {
case IO_SET_CB_RX:
dev->rx_cb = ((io_cb_t *) arg)->cb;
break;
case IO_SET_CB_TX:
dev->tx_cb = ((io_cb_t *) arg)->cb;
break;
case IO_SET_CB_ERR:
dev->err_cb = ((io_cb_t *) arg)->cb;
break;
case IO_SPI_SLAVE_SET_RX_THRESHOLD:
REG_WRITE(RXFTLR, *((uint32_t *) arg));
break;
case IO_SPI_SLAVE_SET_TX_THRESHOLD:
REG_WRITE(TXFTLR, *((uint32_t *) arg));
break;
case IO_SPI_SLAVE_SET_PACKING:
{ /* DFS must be set prior applying this option */
regval = REG_READ(CTRL0);
if (*((uint32_t *) arg) == 0) { /* reset packing */
dev->log_xfer_size = dev->max_xfer_size >> 4;
} else { /* set packing */
if (dev->max_xfer_size == 32) { /* 32-bits SPI */
regval = (regval >> 16) & 0x01F; // Get DFS field from CTRL0 value
dev->log_xfer_size =
(regval == 15) ? 1 : (regval ==
7) ? 0 : dev->
max_xfer_size >> 4;
} else { /* 16-bits SPI */
regval = regval & 0x00F; // Get DFS field from CTRL0 value
dev->log_xfer_size =
(regval == 7) ? 0 : dev->max_xfer_size >> 4;
}
}
break;
}
default:
{
/* ioctl calls that require disabling of the SPI first */
REG_WRITE(SPIEN, 0);
regval = REG_READ(CTRL0);
switch (cmd) {
case IO_SPI_SLAVE_SET_TRANSFER_MODE:
REG_WRITE_BITS(CTRL0, regval, *((uint32_t *) arg), 2, 8);
break;
case IO_SPI_SLAVE_SET_SCPH:
REG_WRITE_BITS(CTRL0, regval, *((uint32_t *) arg), 1, 6);
break;
case IO_SPI_SLAVE_SET_SCPL:
REG_WRITE_BITS(CTRL0, regval, *((uint32_t *) arg), 1, 7);
break;
case IO_SPI_SLAVE_SET_SRL_MODE:
REG_WRITE_BITS(CTRL0, regval, *((uint32_t *) arg), 1, 11);
break;
case IO_SPI_SLAVE_SET_OUTPUT_ENABLE:
REG_WRITE_BITS(CTRL0, regval, *((uint32_t *) arg), 1, 10);
break;
case IO_SPI_SLAVE_SET_DFS:
REG_WRITE_BITS(CTRL0, regval, ((*((uint32_t *) arg)) - 1),
(3 + dev->log_xfer_size),
((dev->log_xfer_size - 1) << 4));
break;
default:
break;
}
REG_WRITE(SPIEN, 0x1);
break;
}
}
}
static void spi_slv_rx_ISR_proc(uint32_t dev_id)
{
spi_info_pt dev = spi_handles[dev_id];
uint32_t val = 0;
#ifdef __Xdmac
if (dev->dmarxchanid == DMA_NONE) {
#endif
/* read remaining data from fifo */
retrieve_rxfifo(dev);
if (dev->rx_size <= (dev->rx_count << dev->log_xfer_size)) { /* read buffer completely filled, mask RX-avail interrupt */
val = REG_READ(IMR);
REG_WRITE(IMR, (val & ~R_RX_FULL));
}
#ifdef __Xdmac
} else {
uint32_t divisor = 0, remainder = 0;
/* DMA RX xfer done */
_dma_chan_enable((0x1 << dev->dmarxchanid), 0);
_dma_int_clear((0x1 << dev->dmarxchanid));
/* process final data, if it is a partial (half)word */
divisor = dev->rx_size >> dev->log_xfer_size;
remainder = dev->rx_size - (divisor << dev->log_xfer_size);
if (remainder != 0) {
uint32_t mask = ~((~0x0) << (remainder * 8));
if (dev->log_xfer_size == 1) {
((uint16_t *) (dev->rx_buff))[divisor] =
(((uint16_t *) (dev->
rx_buff))[divisor] & ~mask) | (dev->
dmarx_last16
& mask);
} else if (dev->log_xfer_size == 2) {
((uint32_t *) (dev->rx_buff))[divisor] =
(((uint32_t *) (dev->
rx_buff))[divisor] & ~mask) | (dev->
dmarx_last32
& mask);
}
}
}
#endif
}
static void spi_slv_tx_ISR_proc(uint32_t dev_id)
{
spi_info_pt dev = spi_handles[dev_id];
uint32_t val = 0;
#ifdef __Xdmac
if (dev->dmatxchanid == DMA_NONE) {
#endif
if (dev->tx_size <= (dev->tx_count << dev->log_xfer_size)) {
/* no data left to put into the fifo, mask TX-request */
val = REG_READ(IMR);
REG_WRITE(IMR, (val & ~R_TX_EMPTY));
} else { /* write data into the fifo */
fill_txfifo(dev);
}
#ifdef __Xdmac
} else {
/* DMA TX xfer done */
_dma_chan_enable((0x1 << dev->dmatxchanid), 0);
_dma_int_clear((0x1 << dev->dmatxchanid));
}
#endif
}
static void spi_slv_idle_ISR_proc(uint32_t dev_id)
{
spi_info_pt dev = spi_handles[dev_id];
uint32_t val = 0;
if (dev->handling_tx == 1) {
if ((dev->tx_size <= (dev->tx_count << dev->log_xfer_size)) || (dev->dmatxchanid != DMA_NONE)) { /* buffer completely processed */
dev->handling_tx = 0;
if (NULL != dev->tx_cb) {
dev->tx_cb(dev_id);
}
/* mask TX-empty (if not done yet) and Idle interrupt */
val = REG_READ(IMR);
REG_WRITE(IMR, (val & ~R_TX_EMPTY & ~R_IDLE));
}
}
if (dev->handling_rx == 1) {
#ifdef __Xdmac
if (dev->dmarxchanid == DMA_NONE) {
#endif
/* read remaining data from fifo */
retrieve_rxfifo(dev);
#ifdef __Xdmac
}
#endif
if ((dev->rx_size <= (dev->rx_count << dev->log_xfer_size)) || (dev->dmarxchanid != DMA_NONE)) { /* buffer completely processed */
dev->handling_rx = 0;
if (NULL != dev->rx_cb) {
dev->rx_cb(dev_id);
}
/* mask RX-available (if not done yet) and Idle interrupt */
val = REG_READ(IMR);
REG_WRITE(IMR, (val & ~R_RX_FULL & ~R_IDLE));
}
}
/* clear idle interrupt */
REG_WRITE(ICR, R_IDLE);
}
static void spi_slv_err_ISR_proc(uint32_t dev_id)
{
spi_info_pt dev = spi_handles[dev_id];
REG_WRITE(IMR, 0);
if (NULL != dev->err_cb) {
dev->err_cb(dev_id);
}
REG_WRITE(ICR, R_RX_OVER | R_RX_UNDER | R_TX_OVER | R_TX_UNDER);
}
static void fill_txfifo(spi_info_pt dev)
{
uint32_t cnt = 0, h = 0, free = 0;
cnt = dev->tx_size - (dev->tx_count << dev->log_xfer_size);
free = (dev->fifo_depth - REG_READ(TXFLR)) << dev->log_xfer_size;
if (cnt > free) {
cnt = free;
}
if (dev->log_xfer_size == 0) { /* 8-bits data */
for (h = 0; h != cnt; h++) {
REG_WRITE(DR, ((uint8_t *) (dev->tx_buff))[dev->tx_count++]);
}
} else if (dev->log_xfer_size == 1) { /* 16-bits data */
for (h = 0; h != cnt / 2; h++) {
REG_WRITE(DR, ((uint16_t *) (dev->tx_buff))[dev->tx_count++]);
}
/* if 2h != cnt: partial tx left at the end */
if (2 * h != cnt) {
REG_WRITE(DR,
((((uint16_t *) (dev->tx_buff))[dev->
tx_count++]) &
0x00ff));
}
} else { /* log_xfer_size == 2; 32-bits data */
for (h = 0; h != cnt / 4; h++) {
REG_WRITE(DR, ((uint32_t *) (dev->tx_buff))[dev->tx_count++]);
}
/* if 4h != cnt: partial tx left at the end */
if (4 * h != cnt) {
uint32_t mask32 = ~((~0x0) << ((cnt - 4 * h) * 8));
REG_WRITE(DR,
((((uint32_t *) (dev->tx_buff))[dev->
tx_count++]) &
mask32));
}
}
}
static void retrieve_rxfifo(spi_info_pt dev)
{
uint32_t cnt = 0, h = 0, avail = 0;
cnt = dev->rx_size - (dev->rx_count << dev->log_xfer_size);
avail = REG_READ(RXFLR) << dev->log_xfer_size;
if (cnt > avail) {
cnt = avail;
}
if (dev->log_xfer_size == 0) { /* 8-bits data */
for (h = 0; h != cnt; h++) {
((uint8_t *) (dev->rx_buff))[dev->rx_count++] =
(uint8_t) REG_READ(DR);
}
} else if (dev->log_xfer_size == 1) { /* 16-bits data */
for (h = 0; h != cnt / 2; h++) {
((uint16_t *) (dev->rx_buff))[dev->rx_count++] =
(uint16_t) REG_READ(DR);
}
/* if 2h != cnt: partial rx left at the end */
if (2 * h != cnt) {
((uint16_t *) (dev->rx_buff))[dev->rx_count] =
(((uint16_t *) (dev->rx_buff))[dev->
rx_count] & ~0x00ff) |
(REG_READ(DR) & 0x00ff);
dev->rx_count++;
}
} else { /* 32-bits data; log_xfer_size == 2 */
for (h = 0; h != cnt / 4; h++) {
((uint32_t *) (dev->rx_buff))[dev->rx_count++] = REG_READ(DR);
}
/* if 4h != cnt: partial rx left at the end */
if (4 * h != cnt) {
uint32_t mask32 = ~((~0x0) << ((cnt - 4 * h) * 8));
((uint32_t *) (dev->rx_buff))[dev->rx_count] =
(((uint32_t *) (dev->rx_buff))[dev->
rx_count] & ~mask32) |
(REG_READ(DR) & mask32);
dev->rx_count++;
}
}
}
#ifdef __Xdmac
#define SPI_SLV_DMA_RX_CTRL (0x80000017) /* am=b10, i=b0, dw/inc=b..., dtt=b10, r=b1, op=b11 */
#define SPI_SLV_DMA_RX_END_CTRL (0xa0000015) /* am=b10, i=b1, dw/inc=b..., dtt=b10, r=b1, op=b01 */
#define SPI_SLV_DMA_RX_REM_CTRL (0xa0000015) /* am=b10, i=b1, dw/inc=b..., dtt=b10, r=b1, op=b01 */
#define SPI_SLV_DMA_TX_CTRL (0x4000000f) /* am=b01, i=b0, dw/inc=b..., dtt=b01, r=b1, op=b11 */
#define SPI_SLV_DMA_TX_END_CTRL (0x6000000d) /* am=b01, i=b1, dw/inc=b..., dtt=b01, r=b1, op=b01 */
#define SPI_SLV_DMA_TX_REM_CTRL (0x6000000d) /* am=b01, i=b1, dw/inc=b..., dtt=b01, r=b1, op=b01 */
#define SPI_SLV_DMA_CTRL_DWINC_POS (5)
#define SPI_SLV_DMA_CTRL_SIZE_POS (8)
#define SPI_SLV_DMA_CTRL_XFER_POS (21)
#define SPI_SLV_DMA_FORCE_INT (0x1 << 29)
static void create_dma_descriptors_rx(spi_info_pt dev, uint8_t *dest,
uint32_t size, uint32_t burst)
{
uint32_t divisor = 0, remainder = 0;
divisor = size >> dev->log_xfer_size;
remainder = size - (divisor << dev->log_xfer_size);
if (dev->log_xfer_size == 0) {
dev->dmarxdescriptor[0] =
SPI_SLV_DMA_RX_END_CTRL | (burst << SPI_SLV_DMA_CTRL_XFER_POS)
| ((size - 1) << SPI_SLV_DMA_CTRL_SIZE_POS);
dev->dmarxdescriptor[2] = (uint32_t) dest + (size - 1);
if (dev->dmarxchanid >= DMAC_MEM_CHAN_CNT) {
dev->dmarxdescriptor[3] = 0;
}
} else if ((divisor > 0) && (remainder == 0)) {
dev->dmarxdescriptor[0] =
SPI_SLV_DMA_RX_END_CTRL | (burst << SPI_SLV_DMA_CTRL_XFER_POS)
| ((size - 1) << SPI_SLV_DMA_CTRL_SIZE_POS)
| ((2 * dev->log_xfer_size + 1) << SPI_SLV_DMA_CTRL_DWINC_POS);
dev->dmarxdescriptor[2] = (uint32_t) dest + (size - 1);
if (dev->dmarxchanid >= DMAC_MEM_CHAN_CNT) {
dev->dmarxdescriptor[3] = 0;
}
} else if ((divisor > 0) && (remainder > 0)) {
dev->dmarxdescriptor[0] =
SPI_SLV_DMA_RX_CTRL | (burst << SPI_SLV_DMA_CTRL_XFER_POS)
| ((size - 1 - remainder) << SPI_SLV_DMA_CTRL_SIZE_POS)
| ((2 * dev->log_xfer_size + 1) << SPI_SLV_DMA_CTRL_DWINC_POS);
dev->dmarxdescriptor[2] = (uint32_t) dest + (size - 1 - remainder);
if (dev->dmarxchanid >= DMAC_MEM_CHAN_CNT) {
dev->dmarxdescriptor[0] |= SPI_SLV_DMA_FORCE_INT;
dev->dmarxdescriptor[3] =
(uint32_t) &(dev->dmarxdescriptor[4]);
}
dev->dmarxdescriptor[4 + 0] =
SPI_SLV_DMA_RX_REM_CTRL | (burst << SPI_SLV_DMA_CTRL_XFER_POS)
| ((2 * dev->log_xfer_size - 1) << SPI_SLV_DMA_CTRL_SIZE_POS)
| ((2 * dev->log_xfer_size + 1) << SPI_SLV_DMA_CTRL_DWINC_POS);
if (dev->log_xfer_size == 1) {
dev->dmarxdescriptor[4 + 2] =
(uint32_t) &(dev->dmarx_last16) + 1;
} else {
dev->dmarxdescriptor[4 + 2] =
(uint32_t) &(dev->dmarx_last32) + 3;
}
if (dev->dmarxchanid >= DMAC_MEM_CHAN_CNT) {
dev->dmarxdescriptor[4 + 3] = 0;
}
} else { /* divisor == 0, remainder > 0 */
dev->dmarxdescriptor[0] =
SPI_SLV_DMA_RX_REM_CTRL | (burst << SPI_SLV_DMA_CTRL_XFER_POS)
| ((2 * dev->log_xfer_size - 1) << SPI_SLV_DMA_CTRL_SIZE_POS)
| ((2 * dev->log_xfer_size + 1) << SPI_SLV_DMA_CTRL_DWINC_POS);
if (dev->log_xfer_size == 1) {
dev->dmarxdescriptor[2] = (uint32_t) &(dev->dmarx_last16) + 1;
} else {
dev->dmarxdescriptor[2] = (uint32_t) &(dev->dmarx_last32) + 3;
}
if (dev->dmarxchanid >= DMAC_MEM_CHAN_CNT) {
dev->dmarxdescriptor[3] = 0;
}
}
}
static void create_dma_descriptors_tx(spi_info_pt dev, uint8_t *src,
uint32_t size, uint32_t burst)
{
uint32_t divisor = 0, remainder = 0;
divisor = size >> dev->log_xfer_size;
remainder = size - (divisor << dev->log_xfer_size);
if (dev->log_xfer_size == 1) {
dev->dmatx_last16 =
((uint16_t *) (dev->
tx_buff))[divisor] & ~((~0x0) << (remainder *
8));
} else {
dev->dmatx_last32 =
((uint32_t *) (dev->
tx_buff))[divisor] & ~((~0x0) << (remainder *
8));
}
if (dev->log_xfer_size == 0) {
dev->dmatxdescriptor[0] =
SPI_SLV_DMA_TX_END_CTRL | (burst << SPI_SLV_DMA_CTRL_XFER_POS)
| ((size - 1) << SPI_SLV_DMA_CTRL_SIZE_POS);
dev->dmatxdescriptor[1] = (uint32_t) src + (size - 1);
if (dev->dmatxchanid >= DMAC_MEM_CHAN_CNT) {
dev->dmatxdescriptor[3] = 0;
}
} else if ((divisor > 0) && (remainder == 0)) {
dev->dmatxdescriptor[0] =
SPI_SLV_DMA_TX_END_CTRL | (burst << SPI_SLV_DMA_CTRL_XFER_POS)
| ((size - 1) << SPI_SLV_DMA_CTRL_SIZE_POS)
| ((2 * dev->log_xfer_size + 1) << SPI_SLV_DMA_CTRL_DWINC_POS);
dev->dmatxdescriptor[1] = (uint32_t) src + (size - 1);
if (dev->dmatxchanid >= DMAC_MEM_CHAN_CNT) {
dev->dmatxdescriptor[3] = 0;
}
} else if ((divisor > 0) && (remainder > 0)) {
dev->dmatxdescriptor[0] =
SPI_SLV_DMA_TX_CTRL | (burst << SPI_SLV_DMA_CTRL_XFER_POS)
| ((size - 1 - remainder) << SPI_SLV_DMA_CTRL_SIZE_POS)
| ((2 * dev->log_xfer_size + 1) << SPI_SLV_DMA_CTRL_DWINC_POS);
dev->dmatxdescriptor[1] = (uint32_t) src + (size - 1 - remainder);
if (dev->dmatxchanid >= DMAC_MEM_CHAN_CNT) {
dev->dmatxdescriptor[0] |= SPI_SLV_DMA_FORCE_INT;
dev->dmatxdescriptor[3] =
(uint32_t) &(dev->dmatxdescriptor[4]);
}
dev->dmatxdescriptor[4 + 0] =
SPI_SLV_DMA_TX_REM_CTRL | (burst << SPI_SLV_DMA_CTRL_XFER_POS)
| ((2 * dev->log_xfer_size - 1) << SPI_SLV_DMA_CTRL_SIZE_POS)
| ((2 * dev->log_xfer_size + 1) << SPI_SLV_DMA_CTRL_DWINC_POS);
if (dev->log_xfer_size == 1) {
dev->dmatxdescriptor[4 + 1] =
(uint32_t) &(dev->dmatx_last16) + 1;
} else {
dev->dmatxdescriptor[4 + 1] =
(uint32_t) &(dev->dmatx_last32) + 3;
}
if (dev->dmatxchanid >= DMAC_MEM_CHAN_CNT) {
dev->dmatxdescriptor[4 + 3] = 0;
}
} else { /* divisor == 0, remainder > 0 */
dev->dmatxdescriptor[0] =
SPI_SLV_DMA_TX_REM_CTRL | (burst << SPI_SLV_DMA_CTRL_XFER_POS)
| ((2 * dev->log_xfer_size - 1) << SPI_SLV_DMA_CTRL_SIZE_POS)
| ((2 * dev->log_xfer_size + 1) << SPI_SLV_DMA_CTRL_DWINC_POS);
if (dev->log_xfer_size == 1) {
dev->dmatxdescriptor[1] = (uint32_t) &(dev->dmatx_last16) + 1;
} else {
dev->dmatxdescriptor[1] = (uint32_t) &(dev->dmatx_last32) + 3;
}
if (dev->dmatxchanid >= DMAC_MEM_CHAN_CNT) {
dev->dmatxdescriptor[3] = 0;
}
}
}
#endif
#endif

View File

@@ -1,416 +0,0 @@
/* ------------------------------------------
* Copyright (c) 2018, 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.
*
--------------------------------------------- */
#include "embARC_error.h"
#include "embARC_toolchain.h"
#include "arc/arc_exception.h"
#include "device/subsystem/spi_master.h"
#include "device/subsystem/ss_spi_master.h"
int32_t ss_spi_master_open(SS_SPI_MASTER_DEV_CONTEXT *ctx, uint32_t mode, uint32_t param)
{
uint32_t dev_id = ctx->dev_id;
DEV_SPI_INFO *info = ctx->info;
io_cb_t callback;
uint32_t val;
if (mode != DEV_MASTER_MODE) {
return E_PAR;
}
if (info->opn_cnt > 0) {
if (param != info->freq) {
return E_OPNED;
} else {
return E_OK;
}
}
if (io_spi_master_open(dev_id)) {
return E_SYS;
}
callback.cb = (IO_CB_FUNC)ctx->int_rx_cb;
io_spi_master_ioctl(dev_id, IO_SET_CB_RX, &callback);
callback.cb = (IO_CB_FUNC)ctx->int_tx_cb;
io_spi_master_ioctl(dev_id, IO_SET_CB_TX, &callback);
callback.cb = (IO_CB_FUNC)ctx->int_err_cb;
io_spi_master_ioctl(dev_id, IO_SET_CB_ERR, &callback);
io_spi_master_ioctl(dev_id, IO_SPI_MASTER_SET_DFS, &info->dfs);
val = 1;
io_spi_master_ioctl(dev_id, IO_SPI_MASTER_SET_PACKING, &val);
info->freq = param;
param = ctx->bus_freq / param;
io_spi_master_ioctl(dev_id, IO_SPI_MASTER_SET_BAUD, &param);
info->opn_cnt++;
ctx->flags = 0;
/* cs pin will toggle when FIFO is empty, to avoid this, spi master operation
* should not be interruptted by others. so set int pri to INT_PRI_MIN
*/
int_enable(ctx->intno_rx);
int_pri_set(ctx->intno_rx, INT_PRI_MIN);
int_enable(ctx->intno_tx);
int_pri_set(ctx->intno_tx, INT_PRI_MIN);
int_enable(ctx->intno_idle);
int_pri_set(ctx->intno_idle, INT_PRI_MIN);
int_enable(ctx->intno_err);
int_pri_set(ctx->intno_err, INT_PRI_MIN);
return E_OK;
}
int32_t ss_spi_master_close(SS_SPI_MASTER_DEV_CONTEXT *ctx)
{
DEV_SPI_INFO *info = ctx->info;
info->opn_cnt--;
if (info->opn_cnt == 0) {
io_spi_master_close(ctx->dev_id);
int_disable(ctx->intno_rx);
int_disable(ctx->intno_tx);
int_disable(ctx->intno_idle);
int_disable(ctx->intno_err);
info->status = DEV_DISABLED;
ctx->flags = 0;
} else {
return E_OPNED;
}
return E_OK;
}
int32_t ss_spi_master_control(SS_SPI_MASTER_DEV_CONTEXT *ctx, uint32_t ctrl_cmd, void *param)
{
uint32_t dev_id = ctx->dev_id;
DEV_SPI_INFO *info = ctx->info;
uint32_t val32 = (uint32_t)param;
DEV_BUFFER *buf = (DEV_BUFFER *)param;
DEV_SPI_TRANSFER *spi_xfer = &(info->xfer);
switch (ctrl_cmd) {
case SPI_CMD_SET_TXINT_BUF:
if (buf && !(ctx->flags & SS_SPI_MASTER_FLAG_BUSY)) {
DEV_SPI_XFER_SET_TXBUF(spi_xfer, buf->buf, buf->ofs, buf->len);
ctx->flags |= SS_SPI_MASTER_FLAG_TX_READY;
} else {
return E_NOSPT;
}
break;
case SPI_CMD_SET_TXINT:
if (val32 && (ctx->flags & SS_SPI_MASTER_FLAG_TX_READY) && !(ctx->flags & SS_SPI_MASTER_FLAG_BUSY)) {
ctx->flags |= SS_SPI_MASTER_FLAG_BUSY;
val32 = SPI_TRANSMIT_ONLY_MODE;
io_spi_master_ioctl(dev_id, IO_SPI_MASTER_SET_TRANSFER_MODE, &val32);
io_spi_master_write(dev_id, spi_xfer->tx_buf + spi_xfer->tx_ofs,
&spi_xfer->tx_len);
} else {
return E_SYS;
}
break;
case SPI_CMD_SET_RXINT_BUF:
if (buf && !(ctx->flags & SS_SPI_MASTER_FLAG_BUSY)) {
DEV_SPI_XFER_SET_RXBUF(spi_xfer, buf->buf, buf->ofs, buf->len);
ctx->flags |= SS_SPI_MASTER_FLAG_RX_READY;
} else {
return E_NOSPT;
}
break;
case SPI_CMD_SET_RXINT:
if (val32 && (ctx->flags & SS_SPI_MASTER_FLAG_RX_READY) && !(ctx->flags & SS_SPI_MASTER_FLAG_BUSY)) {
ctx->flags |= SS_SPI_MASTER_FLAG_BUSY;
val32 = SPI_RECEIVE_ONLY_MODE;
io_spi_master_ioctl(dev_id, IO_SPI_MASTER_SET_TRANSFER_MODE, &val32);
io_spi_master_read(dev_id, spi_xfer->rx_buf + spi_xfer->rx_ofs,
&spi_xfer->rx_len);
} else {
return E_SYS;
}
break;
case SPI_CMD_TRANSFER_INT:
if (param != NULL && !(ctx->flags & SS_SPI_MASTER_FLAG_BUSY)) {
ctx->flags = SS_SPI_MASTER_FLAG_BUSY | SS_SPI_MASTER_FLAG_TX_RX;
*spi_xfer = *((DEV_SPI_TRANSFER *)param);
if (spi_xfer->rx_len == 0) {
val32 = SPI_TRANSMIT_ONLY_MODE;
ctx->flags |= SS_SPI_MASTER_FLAG_TX_READY;
io_spi_master_ioctl(dev_id, IO_SPI_MASTER_SET_TRANSFER_MODE, &val32);
io_spi_master_write(dev_id, spi_xfer->tx_buf, &spi_xfer->tx_len);
} else if (spi_xfer->tx_len == 0) {
val32 = SPI_RECEIVE_ONLY_MODE;
ctx->flags |= SS_SPI_MASTER_FLAG_RX_READY;
io_spi_master_ioctl(dev_id, IO_SPI_MASTER_SET_TRANSFER_MODE, &val32);
io_spi_master_read(dev_id, spi_xfer->rx_buf, &spi_xfer->rx_len);
} else if (spi_xfer->rx_ofs == spi_xfer->tx_len && spi_xfer->tx_ofs == 0) {
ctx->flags |= (SS_SPI_MASTER_FLAG_RX_READY | SS_SPI_MASTER_FLAG_TX_READY);
val32 = SPI_RECEIVE_AFTER_TRANSMIT_MODE;
io_spi_master_ioctl(dev_id, IO_SPI_MASTER_SET_TRANSFER_MODE, &val32);
io_spi_master_read(dev_id, spi_xfer->rx_buf, &spi_xfer->rx_len);
io_spi_master_write(dev_id, spi_xfer->tx_buf, &spi_xfer->tx_len);
} else {
if (spi_xfer->tx_ofs != 0 || spi_xfer->rx_ofs != 0) {
return E_NOSPT;
}
ctx->flags |= (SS_SPI_MASTER_FLAG_RX_READY | SS_SPI_MASTER_FLAG_TX_READY);
DEV_SPI_XFER_INIT(spi_xfer);
val32 = SPI_TRANSMIT_RECEIVE_MODE;
io_spi_master_ioctl(dev_id, IO_SPI_MASTER_SET_TRANSFER_MODE, &val32);
io_spi_master_read(dev_id, spi_xfer->rx_buf, &spi_xfer->tot_len);
io_spi_master_write(dev_id, spi_xfer->tx_buf, &spi_xfer->tot_len);
}
} else {
return E_NOSPT;
}
break;
case SPI_CMD_TRANSFER_POLLING:
if (param != NULL && !(ctx->flags & SS_SPI_MASTER_FLAG_BUSY)) {
spi_xfer = (DEV_SPI_TRANSFER *)param;
while (spi_xfer != NULL) {
ctx->flags = SS_SPI_MASTER_FLAG_BUSY;
DEV_SPI_XFER_INIT(spi_xfer);
io_spi_master_polling(dev_id, spi_xfer);
ctx->flags &= ~SS_SPI_MASTER_FLAG_BUSY;
spi_xfer = spi_xfer->next;
}
} else {
return E_NOSPT;
}
break;
case SPI_CMD_SET_TXCB:
info->spi_cbs.tx_cb = param;
break;
case SPI_CMD_SET_RXCB:
info->spi_cbs.rx_cb = param;
break;
case SPI_CMD_SET_XFERCB:
info->spi_cbs.xfer_cb = param;
break;
case SPI_CMD_SET_ERRCB:
info->spi_cbs.err_cb = param;
break;
case SPI_CMD_SET_CLK_MODE:
switch (val32) {
case SPI_CPOL_0_CPHA_0:
val32 = 0;
io_spi_master_ioctl(dev_id, IO_SPI_MASTER_SET_SCPL, &val32);
io_spi_master_ioctl(dev_id, IO_SPI_MASTER_SET_SCPH, &val32);
break;
case SPI_CPOL_0_CPHA_1:
val32 = 0;
io_spi_master_ioctl(dev_id, IO_SPI_MASTER_SET_SCPL, &val32);
val32 = 1;
io_spi_master_ioctl(dev_id, IO_SPI_MASTER_SET_SCPH, &val32);
break;
case SPI_CPOL_1_CPHA_0:
val32 = 1;
io_spi_master_ioctl(dev_id, IO_SPI_MASTER_SET_SCPL, &val32);
val32 = 0;
io_spi_master_ioctl(dev_id, IO_SPI_MASTER_SET_SCPH, &val32);
break;
case SPI_CPOL_1_CPHA_1:
val32 = 1;
io_spi_master_ioctl(dev_id, IO_SPI_MASTER_SET_SCPL, &val32);
io_spi_master_ioctl(dev_id, IO_SPI_MASTER_SET_SCPH, &val32);
break;
}
break;
case SPI_CMD_SET_DFS:
io_spi_master_ioctl(dev_id, IO_SPI_MASTER_SET_DFS, &val32);
break;
case SPI_CMD_MST_SET_FREQ:
info->freq = val32;
val32 = ctx->bus_freq / val32;
io_spi_master_ioctl(dev_id, IO_SPI_MASTER_SET_BAUD, &val32);
break;
case SPI_CMD_MST_SEL_DEV:
info->slave = val32;
val32 = (1 << val32);
io_spi_master_ioctl(dev_id, IO_SPI_MASTER_SET_SE, &val32);
break;
case SPI_CMD_MST_DSEL_DEV:
val32 = info->slave & (~(1 << val32));
info->slave = SPI_SLAVE_NOT_SELECTED;
io_spi_master_ioctl(dev_id, IO_SPI_MASTER_SET_SE, &val32);
break;
default:
return E_NOSPT;
}
return E_OK;
}
int32_t ss_spi_master_write(SS_SPI_MASTER_DEV_CONTEXT *ctx, const void *data, uint32_t len)
{
uint32_t dev_id = ctx->dev_id;
uint32_t len_ = len;
uint32_t val32 = SPI_TRANSMIT_ONLY_MODE;
/* spi busy */
if (ctx->flags & SS_SPI_MASTER_FLAG_BUSY) {
return E_NORES;
}
if (arc_locked()) {
/*
* not allow to be called in isr or cpu is locked.
* Beacue the bottom drvier is simply interrupt driven
*/
return E_SYS;
}
ctx->flags = SS_SPI_MASTER_FLAG_BUSY;
io_spi_master_ioctl(dev_id, IO_SPI_MASTER_SET_TRANSFER_MODE, &val32);
io_spi_master_write(dev_id, (uint8_t *) data, &len_);
/* wait finished: spi int enable & no cpu lock */
while (ctx->flags & SS_SPI_MASTER_FLAG_BUSY) {
;
}
if (ctx->flags & SS_SPI_MASTER_FLAG_ERROR) {
ctx->flags = 0;
return E_SYS;
}
ctx->flags = 0;
return E_OK;
}
int32_t ss_spi_master_read(SS_SPI_MASTER_DEV_CONTEXT *ctx, void *data, uint32_t len)
{
uint32_t dev_id = ctx->dev_id;
uint32_t len_ = len;
uint32_t val32 = SPI_RECEIVE_ONLY_MODE;
if (ctx->flags & SS_SPI_MASTER_FLAG_BUSY) {
return E_NORES;
}
if (arc_locked()) {
/*
* not allow to be called in isr or cpu is locked.
* Beacue the bottom drvier is simply interrupt driven
*/
return E_SYS;
}
ctx->flags = SS_SPI_MASTER_FLAG_BUSY;
io_spi_master_ioctl(dev_id, IO_SPI_MASTER_SET_TRANSFER_MODE, &val32);
io_spi_master_read(dev_id, (uint8_t *)data, &len_);
while (ctx->flags & SS_SPI_MASTER_FLAG_BUSY) {
;
}
if (ctx->flags & SS_SPI_MASTER_FLAG_ERROR) {
ctx->flags = 0;
return E_SYS;
}
ctx->flags = 0;
return 0;
}
void ss_spi_master_tx_cb(SS_SPI_MASTER_DEV_CONTEXT *ctx, void *param)
{
DEV_SPI_INFO *info = ctx->info;
DEV_SPI_TRANSFER *spi_xfer = &(info->xfer);
if (ctx->flags & SS_SPI_MASTER_FLAG_TX_RX) {
if (spi_xfer->rx_len == 0) {
ctx->flags &= ~SS_SPI_MASTER_FLAG_TX_RX;
if (ctx->flags & SS_SPI_MASTER_FLAG_TX_READY && info->spi_cbs.xfer_cb) {
info->spi_cbs.xfer_cb(info);
}
}
} else if (ctx->flags & SS_SPI_MASTER_FLAG_TX_READY && info->spi_cbs.tx_cb) {
info->spi_cbs.tx_cb(info);
}
ctx->flags &= ~(SS_SPI_MASTER_FLAG_TX_READY | SS_SPI_MASTER_FLAG_BUSY);
}
void ss_spi_master_rx_cb(SS_SPI_MASTER_DEV_CONTEXT *ctx, void *param)
{
DEV_SPI_INFO *info = ctx->info;
if (ctx->flags & SS_SPI_MASTER_FLAG_TX_RX) {
if (ctx->flags & SS_SPI_MASTER_FLAG_RX_READY && info->spi_cbs.xfer_cb) {
info->spi_cbs.xfer_cb(info);
}
ctx->flags &= ~(SS_SPI_MASTER_FLAG_RX_READY | SS_SPI_MASTER_FLAG_TX_READY |
SS_SPI_MASTER_FLAG_BUSY | SS_SPI_MASTER_FLAG_TX_RX);
} else {
if (ctx->flags & SS_SPI_MASTER_FLAG_RX_READY && info->spi_cbs.rx_cb) {
info->spi_cbs.rx_cb(info);
}
ctx->flags &= ~(SS_SPI_MASTER_FLAG_RX_READY | SS_SPI_MASTER_FLAG_BUSY);
}
}
void ss_spi_master_err_cb(SS_SPI_MASTER_DEV_CONTEXT *ctx, void *param)
{
DEV_SPI_INFO *info = ctx->info;
ctx->flags = SS_SPI_MASTER_FLAG_ERROR;
if (info->spi_cbs.err_cb) {
info->spi_cbs.err_cb(info);
}
}

View File

@@ -1,33 +0,0 @@
/* ------------------------------------------
* Copyright (c) 2018, 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.
*
--------------------------------------------- */

View File

@@ -1,440 +0,0 @@
/* ------------------------------------------
* Copyright (c) 2018, 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.
*
--------------------------------------------- */
#include "embARC_error.h"
#include "embARC_toolchain.h"
#include "arc/arc_exception.h"
#include "device/subsystem/uart.h"
#include "device/subsystem/ss_uart.h"
#include "io_config.h"
/* APEX UART device registers */
#define UART_RBR (0x00)
#define UART_THR (0x00)
#define UART_DLL (0x00)
#define UART_IER (0x04)
#define UART_DLH (0x04)
#define UART_IIR (0x08)
#define UART_FCR (0x08)
#define UART_LCR (0x0c)
#define UART_MCR (0x10)
#define UART_LSR (0x14) // unused
#define UART_MSR (0x18) // unused
#define UART_USR (0x7c) // unused
#define UART_CLKEN (0xc0)
#define REG_READ(x) arc_aux_read((ctx->reg_base + x))
#define REG_WRITE(x, y) arc_aux_write((ctx->reg_base + x), y)
/** convert uart baudrate to subsystem divisor */
#define SS_UART_BAUD2DIV(perifreq, baud) ((perifreq) / ((baud) * 16) + 1)
/**
* @fn int32_t set_hwfc(uint32_t dev_id, uint32_t control)
*/
Inline int32_t set_hwfc(uint32_t dev_id, uint32_t control)
{
uint32_t param = 0;
if (control == UART_FC_NONE) {
param = 0;
} else {
param = 1;
}
io_uart_ioctl(dev_id, IO_UART_SET_FLOW_CONTROL, &param);
return E_OK;
}
/**
* @fn int32_t set_baud(SS_UART_DEV_CONTEXT *ctx, uint32_t baud)
*/
Inline int32_t set_baud(SS_UART_DEV_CONTEXT *ctx, uint32_t baud)
{
uint32_t param;
DEV_UART_INFO *info = ctx->info;
param = SS_UART_BAUD2DIV(ctx->bus_freq, baud);
io_uart_ioctl(ctx->dev_id, IO_UART_SET_DLx, &param);
info->baudrate = baud;
return E_OK;
}
static int32_t set_dps(uint32_t dev_id, const UART_DPS_FORMAT *format)
{
uint32_t param = 0;
switch (format->databits) {
case 6:
param |= 0x1;
break;
case 7:
param |= 0x2;
break;
case 8:
param |= 0x3;
break;
default:
return E_NOSPT;
}
if (format->stopbits == UART_STPBITS_ONE) {
} else if (format->stopbits == UART_STPBITS_ONEHALF && format->databits == 5) {
param |= 0x4;
} else {
return E_NOSPT;
}
if (format->parity != UART_PARITY_NONE) {
param |= 0x8; // PEN
if (format->parity == UART_PARITY_EVEN) {
param |= 0x10; // EPS
} else if (format->parity == UART_PARITY_MARK) {
// PEN & Stick parity = logic 1
param |= (0x20);
} else if (format->parity == UART_PARITY_SPACE) {
// PEN & EPS & Stick parity = logic 0
param |= (0x10 | 0x20);
}
}
io_uart_ioctl(dev_id, IO_UART_SET_LCR, &param);
return E_OK;
}
static void io_uart_poll_write(SS_UART_DEV_CONTEXT *ctx, uint8_t *data, uint32_t *size)
{
uint32_t old_val;
uint32_t i = 0;
uint32_t len;
/* disbale uart interrupt */
old_val = REG_READ(UART_IER);
REG_WRITE(UART_IER, 0x80);
len = *size;
while (i < len) {
while ((REG_READ(UART_LSR) & 0x20)) {
; // wait THR empty
}
REG_WRITE(UART_THR, data[i++]);
}
REG_WRITE(UART_IER, old_val);
}
static void io_uart_poll_read(SS_UART_DEV_CONTEXT *ctx, uint8_t *data, uint32_t *size)
{
uint32_t i = 0;
uint32_t len;
uint32_t old_val;
old_val = REG_READ(UART_IER);
REG_WRITE(UART_IER, 0x80);
len = *size;
while (i < len) {
while (!(REG_READ(UART_LSR) & 0x1)) {
; // wait data ready
}
data[i++] = REG_READ(UART_RBR);
}
REG_WRITE(UART_IER, old_val);
}
static void io_uart_rx_int(SS_UART_DEV_CONTEXT *ctx, uint32_t enable)
{
uint32_t val;
if (enable) {
/* enable ERBFI interrupt */
val = REG_READ(UART_IER) | 0x1;
REG_WRITE(UART_IER, val);
} else {
val = REG_READ(UART_IER) & ~0x1;
REG_WRITE(UART_IER, val);
}
}
static void io_uart_tx_int(SS_UART_DEV_CONTEXT *ctx, uint32_t enable)
{
uint32_t val;
if (enable) {
/* enable ETBEI interrupt and enable use of interrupt for TX threshold */
val = REG_READ(UART_IER) | 0x82;
REG_WRITE(UART_IER, val);
} else {
val = REG_READ(UART_IER) & ~0x82;
REG_WRITE(UART_IER, val);
}
}
int32_t ss_uart_open(SS_UART_DEV_CONTEXT *ctx, uint32_t baud)
{
int32_t ret = E_OK;
DEV_UART_INFO *info = ctx->info;
io_cb_t callback;
int32_t dev_id = ctx->dev_id;
info->opn_cnt++;
if (info->opn_cnt > 1) {
if (baud == info->baudrate) {
return E_OK;
} else {
return E_OPNED;
}
}
if (io_uart_open(dev_id)) {
return E_SYS;
}
callback.cb = (IO_CB_FUNC)ctx->tx_cb;
io_uart_ioctl(dev_id, IO_SET_CB_TX, &callback);
callback.cb = (IO_CB_FUNC)ctx->rx_cb;
io_uart_ioctl(dev_id, IO_SET_CB_RX, &callback);
callback.cb = (IO_CB_FUNC)ctx->err_cb;
io_uart_ioctl(dev_id, IO_SET_CB_ERR, &callback);
UART_DPS_FORMAT_DEFAULT(info->dps_format);
set_dps(dev_id, &info->dps_format);
info->hwfc = UART_FC_DEFAULT;
set_hwfc(dev_id, info->hwfc);
set_baud(ctx, baud);
ctx->flags = 0;
info->baudrate = baud;
int_enable(ctx->intno);
return ret;
}
int32_t ss_uart_close(SS_UART_DEV_CONTEXT *ctx)
{
DEV_UART_INFO *info = ctx->info;
info->opn_cnt--;
if (info->opn_cnt == 0) {
info->baudrate = 0;
io_uart_close(ctx->dev_id);
int_disable(ctx->intno);
}
return E_OK;
}
int32_t ss_uart_control(SS_UART_DEV_CONTEXT *ctx, uint32_t ctrl_cmd, void *param)
{
DEV_BUFFER *devbuf;
uint32_t int_val = (uint32_t)param;
int32_t dev_id = ctx->dev_id;
DEV_UART_INFO *info = ctx->info;
switch (ctrl_cmd) {
case UART_CMD_SET_BAUD:
return set_baud(ctx, int_val);
case UART_CMD_SET_HWFC:
io_uart_ioctl(dev_id, IO_UART_SET_FLOW_CONTROL, param);
return E_OK;
case UART_CMD_SET_DPS_FORMAT:
return set_dps(dev_id, (UART_DPS_FORMAT *)param);
case UART_CMD_GET_RXAVAIL:
if (REG_READ(UART_LSR) & 0x1) {
/* at least one byte */
*((uint32_t *)param) = 1;
} else {
*((uint32_t *)param) = 0;
}
return E_OK;
case UART_CMD_GET_TXAVAIL:
int_val = REG_READ(UART_LSR);
if (int_val & 0x40) {
*((uint32_t *)param) = IO_UART0_FS;
} else {
if (int_val & 0x20) {
/* FIFO full */
*((uint32_t *)param) = 0;
} else {
*((uint32_t *)param) = 1;
}
}
return E_OK;
case UART_CMD_SET_RXCB:
info->uart_cbs.rx_cb = param;
return E_OK;
case UART_CMD_SET_TXCB:
info->uart_cbs.tx_cb = param;
return E_OK;
case UART_CMD_SET_ERRCB:
info->uart_cbs.err_cb = param;
return E_OK;
case UART_CMD_SET_TXINT:
io_uart_tx_int(ctx, int_val);
return E_OK;
case UART_CMD_SET_RXINT:
io_uart_rx_int(ctx, int_val);
return E_OK;
case UART_CMD_SET_TXINT_BUF:
if (param != NULL) {
devbuf = (DEV_BUFFER *)param;
info->tx_buf = *devbuf;
info->tx_buf.ofs = 0;
io_uart_write(dev_id, (uint8_t *)(devbuf->buf),
&(devbuf->len));
} else {
info->tx_buf.buf = NULL;
info->tx_buf.len = 0;
info->tx_buf.ofs = 0;
io_uart_write(dev_id, NULL, &(info->tx_buf.len));
}
break;
case UART_CMD_SET_RXINT_BUF:
if (param != NULL) {
devbuf = (DEV_BUFFER *)param;
info->rx_buf = *devbuf;
info->rx_buf.ofs = 0;
io_uart_read(dev_id, (uint8_t *)(devbuf->buf),
&(devbuf->len));
} else {
info->rx_buf.buf = NULL;
info->rx_buf.len = 0;
info->rx_buf.ofs = 0;
io_uart_read(dev_id, NULL, &(info->rx_buf.len));
}
break;
case UART_CMD_BREAK_SET:
case UART_CMD_BREAK_CLR:
return E_NOSPT;
default:
return E_NOSPT;
}
return E_OK;
}
int32_t ss_uart_write(SS_UART_DEV_CONTEXT *ctx, const void *data, uint32_t len)
{
uint32_t dev_id = ctx->dev_id;
if (arc_locked() || arc_int_active()) {
io_uart_poll_write(ctx, (uint8_t *) data, &len);
} else {
ctx->flags = SS_UART_FLAG_TX;
io_uart_write(dev_id, (uint8_t *) data, &len);
/* wait finished: uart int enable & no cpu lock */
while (ctx->flags & SS_UART_FLAG_TX) {
;
}
if (ctx->flags & SS_UART_FLAG_ERROR) {
ctx->flags = 0;
return E_SYS;
}
ctx->flags = 0;
}
return len;
}
int32_t ss_uart_read(SS_UART_DEV_CONTEXT *ctx, void *data, uint32_t len)
{
int32_t dev_id = ctx->dev_id;
if (arc_locked() || arc_int_active()) {
io_uart_poll_read(ctx, (uint8_t *) data, &len);
} else {
ctx->flags = SS_UART_FLAG_RX;
io_uart_read(dev_id, (uint8_t *) data, &len);
/* wait finished: uart int enable & no cpu lock */
while (ctx->flags & SS_UART_FLAG_RX) {
;
}
if (ctx->flags & SS_UART_FLAG_ERROR) {
ctx->flags = 0;
return E_SYS;
}
ctx->flags = 0;
}
return len;
}
void ss_uart_tx_cb(SS_UART_DEV_CONTEXT *ctx, void *param)
{
DEV_UART_INFO *info = ctx->info;
if (ctx->flags & SS_UART_FLAG_TX) {
ctx->flags &= ~SS_UART_FLAG_TX;
} else if (info->uart_cbs.tx_cb) {
info->uart_cbs.tx_cb(info);
}
}
void ss_uart_rx_cb(SS_UART_DEV_CONTEXT *ctx, void *param)
{
DEV_UART_INFO *info = ctx->info;
if (ctx->flags & SS_UART_FLAG_RX) {
ctx->flags &= ~SS_UART_FLAG_RX;
} else if (info->uart_cbs.rx_cb) {
info->uart_cbs.rx_cb(info);
}
}
void ss_uart_err_cb(SS_UART_DEV_CONTEXT *ctx, void *param)
{
DEV_UART_INFO *info = ctx->info;
ctx->flags = SS_UART_FLAG_ERROR;
if (info->uart_cbs.err_cb) {
info->uart_cbs.err_cb(info);
}
}

View File

@@ -1,950 +0,0 @@
/* ==========================================================================
* Synopsys DesignWare Sensor and Control IP Subsystem IO Software Driver and
* documentation (hereinafter, "Software") is an Unsupported proprietary work
* of Synopsys, Inc. unless otherwise expressly agreed to in writing between
* Synopsys and you.
*
* The Software IS NOT an item of Licensed Software or Licensed Product under
* any End User Software License Agreement or Agreement for Licensed Product
* with Synopsys or any supplement thereto. You are permitted to use and
* redistribute this Software in source and binary forms, with or without
* modification, provided that redistributions of source code must retain this
* notice. You may not view, use, disclose, copy or distribute this file or
* any information contained herein except pursuant to this license grant from
* Synopsys. If you do not agree with this notice, including the disclaimer
* below, then you are not authorized to use the Software.
*
* THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS 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.
* ========================================================================== */
/*==========================================================================
* Library DW_DFSS-1.1.6
* ========================================================================== */
#include <stdlib.h>
#include <stddef.h>
#include <stdint.h>
#include "device/subsystem/uart.h"
#include "io_config.h"
#include "apexextensions.h"
/* APEX UART device registers */
#define UART_RBR (0x00)
#define UART_THR (0x00)
#define UART_DLL (0x00)
#define UART_IER (0x04)
#define UART_DLH (0x04)
#define UART_IIR (0x08)
#define UART_FCR (0x08)
#define UART_LCR (0x0c)
#define UART_MCR (0x10)
#define UART_LSR (0x14) // unused
#define UART_MSR (0x18) // unused
#define UART_USR (0x7c) // unused
#define UART_CLKEN (0xc0)
#define DMA_NONE (0xff)
#define FLOW_CONTROL_OFF 0 // Flow Control is OFF
#define FLOW_CONTROL_ON 1 // Using software implementation of CTS/RTS handling
#define nCTS_LOW 0
#define nCTS_HIGH 1
typedef _Interrupt void (*ISR) ();
/* Private data structure maintained by the driver. */
typedef struct uart_info_struct {
uint32_t reg_base; /* base address of device register set */
/* TX & RX Buffer and lengths */
uint8_t *tx_data;
uint32_t tx_size;
uint32_t tx_count;
uint8_t *rx_data;
uint32_t rx_size, *p_rxsize;
uint32_t rx_count;
uint8_t instID;
uint16_t dmarxchanid, dmatxchanid;
#ifdef __Xdmac
_Uncached uint32_t *dmarxdescriptor, *dmatxdescriptor;
uint8_t dmarxidx;
uint8_t dmatxidx;
#endif
/* Callbacks */
IO_CB_FUNC tx_cb;
IO_CB_FUNC rx_cb;
IO_CB_FUNC err_cb;
/* Interrupt numbers and handlers */
uint8_t isr_vector; /* ISR vector */
ISR uart_isr; /* UART device ISRs */
ISR uart_dmatx_isr; /* UART DMA TX ISRs */
ISR uart_dmarx_isr; /* UART DMA RX ISRs */
uint32_t fifo_depth, rx_threshold, tx_threshold;
uint8_t fcr_mirror;
uint8_t flow_control;
uint8_t nCTS_state;
} uart_info_t, *uart_info_pt;
#ifdef IO_UART0_PRESENT
#define UART_DEV_PRESENT
#endif
#ifdef IO_UART1_PRESENT
#define UART_DEV_PRESENT
#endif
#ifdef IO_UART2_PRESENT
#define UART_DEV_PRESENT
#endif
#ifdef IO_UART3_PRESENT
#define UART_DEV_PRESENT
#endif
#ifdef UART_DEV_PRESENT
#define UART_MAX_CNT (4)
static void uart_isr_proc(uint32_t dev_id);
static void uart_dmatx_isr_proc(uint32_t dev_id);
static void uart_dmarx_isr_proc(uint32_t dev_id);
#ifdef IO_UART0_PRESENT
static _Interrupt void uart0_ISR()
{
uart_isr_proc(0);
}
static _Interrupt void uart0_dmatx_ISR()
{
uart_dmatx_isr_proc(0);
}
static _Interrupt void uart0_dmarx_ISR()
{
uart_dmarx_isr_proc(0);
}
#endif
#ifdef IO_UART1_PRESENT
static _Interrupt void uart1_ISR()
{
uart_isr_proc(1);
}
static _Interrupt void uart1_dmatx_ISR()
{
uart_dmatx_isr_proc(1);
}
static _Interrupt void uart1_dmarx_ISR()
{
uart_dmarx_isr_proc(1);
}
#endif
#ifdef IO_UART2_PRESENT
static _Interrupt void uart2_ISR()
{
uart_isr_proc(2);
}
static _Interrupt void uart2_dmatx_ISR()
{
uart_dmatx_isr_proc(2);
}
static _Interrupt void uart2_dmarx_ISR()
{
uart_dmarx_isr_proc(2);
}
#endif
#ifdef IO_UART3_PRESENT
static _Interrupt void uart3_ISR()
{
uart_isr_proc(3);
}
static _Interrupt void uart3_dmatx_ISR()
{
uart_dmatx_isr_proc(3);
}
static _Interrupt void uart3_dmarx_ISR()
{
uart_dmarx_isr_proc(3);
}
#endif
#ifdef __Xdmac
static void create_dma_descriptor_rx(uart_info_pt dev, uint32_t burst,
uint8_t idx);
static void create_dma_descriptor_tx(uart_info_pt dev, uint32_t burst,
uint8_t idx);
#endif
/* UART devices private data structures */
static uart_info_pt uart_handles[UART_MAX_CNT] = { 0 };
#ifdef __Xdmac
static _Uncached uint32_t uart_dmarx_descriptors[8 * UART_MAX_CNT];
static _Uncached uint32_t uart_dmatx_descriptors[8 * UART_MAX_CNT];
#endif
static uart_info_t uart_devs[] = {
#ifdef IO_UART0_PRESENT
{ .instID = 0,
.reg_base = AR_IO_UART0_RBR_THR_DLL,
.isr_vector = IO_UART0_INTR,
.uart_isr = uart0_ISR,
.uart_dmatx_isr = uart0_dmatx_ISR,
.uart_dmarx_isr = uart0_dmarx_ISR,
#ifdef IO_UART0_DMA_RX
.dmarxchanid = IO_UART0_DMA_RX,
#else
.dmarxchanid = DMA_NONE,
#endif
#ifdef IO_UART0_DMA_TX
.dmatxchanid = IO_UART0_DMA_TX,
#else
.dmatxchanid = DMA_NONE,
#endif
.fifo_depth = IO_UART0_FS },
#endif
#ifdef IO_UART1_PRESENT
{ .instID = 1,
.reg_base = AR_IO_UART1_RBR_THR_DLL,
.isr_vector = IO_UART1_INTR,
.uart_isr = uart1_ISR,
.uart_dmatx_isr = uart1_dmatx_ISR,
.uart_dmarx_isr = uart1_dmarx_ISR,
#ifdef IO_UART1_DMA_RX
.dmarxchanid = IO_UART1_DMA_RX,
#else
.dmarxchanid = DMA_NONE,
#endif
#ifdef IO_UART1_DMA_TX
.dmatxchanid = IO_UART1_DMA_TX,
#else
.dmatxchanid = DMA_NONE,
#endif
.fifo_depth = IO_UART1_FS },
#endif
#ifdef IO_UART2_PRESENT
{ .instID = 2,
.reg_base = AR_IO_UART2_RBR_THR_DLL,
.isr_vector = IO_UART2_INTR,
.uart_isr = uart2_ISR,
.uart_dmatx_isr = uart2_dmatx_ISR,
.uart_dmarx_isr = uart2_dmarx_ISR,
#ifdef IO_UART2_DMA_RX
.dmarxchanid = IO_UART2_DMA_RX,
#else
.dmarxchanid = DMA_NONE,
#endif
#ifdef IO_UART2_DMA_TX
.dmatxchanid = IO_UART2_DMA_TX,
#else
.dmatxchanid = DMA_NONE,
#endif
.fifo_depth = IO_UART2_FS },
#endif
#ifdef IO_UART3_PRESENT
{ .instID = 3,
.reg_base = AR_IO_UART3_RBR_THR_DLL,
.isr_vector = IO_UART3_INTR,
.uart_isr = uart3_ISR,
.uart_dmatx_isr = uart3_dmatx_ISR,
.uart_dmarx_isr = uart3_dmarx_ISR,
#ifdef IO_UART3_DMA_RX
.dmarxchanid = IO_UART3_DMA_RX,
#else
.dmarxchanid = DMA_NONE,
#endif
#ifdef IO_UART3_DMA_TX
.dmatxchanid = IO_UART3_DMA_TX,
#else
.dmatxchanid = DMA_NONE,
#endif
.fifo_depth = IO_UART3_FS },
#endif
{ .instID = UART_MAX_CNT }
};
#define REG_WRITE(reg, x) _sr((unsigned)(x), (unsigned)(dev->reg_base + reg))
#define REG_READ(reg) _lr((unsigned)(dev->reg_base + reg))
uint32_t io_uart_open(uint32_t dev_id)
{
uint32_t h = 0;
uint32_t val = 0;
uart_info_pt dev;
h = 0;
while ((uart_devs[h].instID != dev_id)
&& (uart_devs[h].instID != UART_MAX_CNT)) {
h++;
}
if ((uart_devs[h].instID == UART_MAX_CNT) || (0 != uart_handles[dev_id])) { /* dev_id not part of design, or still open */
return 1;
}
uart_handles[dev_id] = &uart_devs[h];
dev = uart_handles[dev_id];
REG_WRITE(UART_CLKEN, 0x1);
REG_WRITE(UART_IER, 0x0);
REG_READ(UART_RBR);
/* when there are fifos available, always enable and reset these */
if (dev->fifo_depth != 0) {
REG_WRITE(UART_FCR, 0x07);
dev->fcr_mirror = 0;
dev->rx_threshold = 1;
dev->tx_threshold = 0;
}
/* save nCTS state */
val = REG_READ(UART_MSR);
dev->nCTS_state = (val & 0x10) ? nCTS_LOW : nCTS_HIGH;
_setvecti(dev->isr_vector, dev->uart_isr);
#ifdef __Xdmac
dev->dmarxdescriptor = &uart_dmarx_descriptors[8 * h];
dev->dmatxdescriptor = &uart_dmatx_descriptors[8 * h];
if (dev->dmarxchanid != DMA_NONE) {
dev->dmarxdescriptor[1] = dev->dmarxdescriptor[4 + 1] =
dev->reg_base + UART_RBR;
dev->dmarxdescriptor[3] = (uint32_t) &(dev->dmarxdescriptor[4]);
dev->dmarxdescriptor[4 + 3] =
(uint32_t) &(dev->dmarxdescriptor[0]);
_setvecti(DMAC_INT_BASE + dev->dmarxchanid, dev->uart_dmarx_isr);
_setvecti(DMAC_ERR_BASE + dev->dmarxchanid, dev->uart_isr);
}
if (dev->dmatxchanid != DMA_NONE) {
dev->dmatxdescriptor[2] = dev->dmatxdescriptor[4 + 2] =
dev->reg_base + UART_THR;
dev->dmatxdescriptor[3] = (uint32_t) &(dev->dmatxdescriptor[4]);
dev->dmatxdescriptor[4 + 3] =
(uint32_t) &(dev->dmatxdescriptor[0]);
_setvecti(DMAC_INT_BASE + dev->dmatxchanid, dev->uart_dmatx_isr);
_setvecti(DMAC_ERR_BASE + dev->dmatxchanid, dev->uart_isr);
}
#endif
return 0;
}
void io_uart_close(uint32_t dev_id)
{
uart_info_pt dev = uart_handles[dev_id];
// bring uart instance to reset state
if (dev->fifo_depth != 0) {
REG_WRITE(UART_FCR, 0x07); // reset FIFOs
}
REG_WRITE(UART_IER, 0x0); // clear interrupt enable register
/* gate the UART clock */
REG_WRITE(UART_CLKEN, 0x0);
_setvecti(dev->isr_vector, NULL);
#ifdef __Xdmac
if (dev->dmarxchanid != DMA_NONE) {
_setvecti(DMAC_INT_BASE + dev->dmarxchanid, NULL);
_setvecti(DMAC_ERR_BASE + dev->dmarxchanid, NULL);
_dma_chan_reset(0x1 << dev->dmarxchanid);
}
if (dev->dmatxchanid != DMA_NONE) {
_setvecti(DMAC_INT_BASE + dev->dmatxchanid, NULL);
_setvecti(DMAC_ERR_BASE + dev->dmatxchanid, NULL);
_dma_chan_reset(0x1 << dev->dmatxchanid);
}
#endif
dev->rx_cb = NULL;
dev->tx_cb = NULL;
dev->err_cb = NULL;
uart_handles[dev_id] = 0;
}
void io_uart_read(uint32_t dev_id, uint8_t *data, uint32_t *size)
{
uart_info_pt dev = uart_handles[dev_id];
uint32_t val = 0;
dev->rx_data = data;
dev->rx_size = *size;
dev->p_rxsize = size;
dev->rx_count = 0;
#ifdef __Xdmac
if (dev->dmarxchanid == DMA_NONE) {
#endif
if (dev->rx_size > 0) {
if ((dev->fifo_depth != 0) && (dev->rx_size < dev->rx_threshold)) {
/* temporary reset the rx_threshold to 1 */
REG_WRITE(UART_FCR, (((dev->fcr_mirror & ~0xC) << 4) | 0x01));
}
/* enable ERBFI and ELSI interrupt */
val = REG_READ(UART_IER) | 0x5;
REG_WRITE(UART_IER, val);
}
#ifdef __Xdmac
} else { /* DMA: create descriptor */
if (dev->rx_size != 0) {
if (dev->fifo_depth == 0) { /* fifos are not available */
val = 1;
} else {
val = dev->rx_threshold;
}
create_dma_descriptor_rx(dev, val, 0);
if (dev->rx_size != dev->rx_count) {
create_dma_descriptor_rx(dev, val, 4);
}
/* init dma */
if (dev->dmarxchanid < DMAC_MEM_CHAN_CNT) {
_dma_chan_desc(dev->dmarxchanid,
&(dev->dmarxdescriptor[0]));
} else {
_dma_chan_desc_aux(dev->dmarxchanid,
&(dev->dmarxdescriptor[0]));
}
dev->dmarxidx = 0;
_dma_chan_enable((0x1 << dev->dmarxchanid), 1);
/* enable ELSI interrupt */
val = REG_READ(UART_IER) | 0x4;
REG_WRITE(UART_IER, val);
}
}
/*
* De-assert nRTS line if flow control is enabled
* Note that UART controller inverts the MCR bit value
*/
if (dev->flow_control == FLOW_CONTROL_ON) {
val = REG_READ(UART_MCR) | 0x2;
REG_WRITE(UART_MCR, val);
}
#endif
}
void io_uart_write(uint32_t dev_id, uint8_t *data, uint32_t *size)
{
uart_info_pt dev = uart_handles[dev_id];
uint32_t cnt = 0;
uint32_t h = 0;
uint32_t val = 0;
dev->tx_data = data;
dev->tx_size = *size;
dev->tx_count = 0;
#ifdef __Xdmac
if (dev->dmatxchanid == DMA_NONE) {
#endif
/* If...
* - flow control is disabled or
* - flow control is enabled && nCTS is already LOW
* ...start data transmit immediately, wait for nCTS change IRQ otherwise */
if ((dev->flow_control == FLOW_CONTROL_OFF) ||
((dev->flow_control == FLOW_CONTROL_ON)
&& (dev->nCTS_state == nCTS_LOW))) {
/* write first bytes to fifo (if any) */
cnt = dev->tx_size - dev->tx_count;
if (cnt > 0) {
if (dev->fifo_depth == 0) { /* fifos are not available */
cnt = 1;
} else if (cnt > dev->fifo_depth) { /* fifos enabled (and by definition != FIFO_NONE) */
cnt = dev->fifo_depth;
}
for (h = 0; h != cnt; h++) {
REG_WRITE(UART_THR, (dev->tx_data[dev->tx_count++]));
}
/* enable ETBEI interrupt and enable use of interrupt for TX threshold */
val = REG_READ(UART_IER) | 0x82;
REG_WRITE(UART_IER, val);
}
}
#ifdef __Xdmac
} else {
/* DMA: create descriptor */
if (dev->fifo_depth == 0) { /* fifos are not available */
cnt = 1;
} else {
cnt = dev->fifo_depth - dev->tx_threshold;
}
create_dma_descriptor_tx(dev, cnt, 0);
if (dev->tx_size != dev->tx_count) {
create_dma_descriptor_tx(dev, cnt, 4);
}
/* init dma */
if (dev->dmatxchanid < DMAC_MEM_CHAN_CNT) {
_dma_chan_desc(dev->dmatxchanid, &(dev->dmatxdescriptor[0]));
} else {
_dma_chan_desc_aux(dev->dmatxchanid,
&(dev->dmatxdescriptor[0]));
}
dev->dmatxidx = 0;
/* If nCTS is already LOW and flow control is enabled - start data transmit immediately,
* wait for nCTS change IRQ otherwise */
if (!
((dev->flow_control == FLOW_CONTROL_ON)
&& (dev->nCTS_state == nCTS_HIGH))) {
_dma_chan_enable((0x1 << dev->dmatxchanid), 1);
}
}
#endif
}
void io_uart_ioctl(uint32_t dev_id, uint32_t cmd, void *arg)
{
uart_info_pt dev = uart_handles[dev_id];
uint32_t val = 0;
switch (cmd) {
case IO_SET_CB_RX:
dev->rx_cb = ((io_cb_t *) arg)->cb;
break;
case IO_SET_CB_TX:
dev->tx_cb = ((io_cb_t *) arg)->cb;
break;
case IO_SET_CB_ERR:
dev->err_cb = ((io_cb_t *) arg)->cb;
break;
#if 0
case IO_UART_SET_MCR: // not part of public API (yet)
REG_WRITE(UART_MCR, *((uint32_t *) arg));
break;
case IO_UART_GET_MCR: // not part of public API (yet)
*((uint32_t *) arg) = REG_READ(UART_MCR);
break;
#endif
case IO_UART_SET_LCR:
/* leave the LDAB bit cleared */
REG_WRITE(UART_LCR, (*((uint32_t *) arg) & 0x7f));
break;
case IO_UART_GET_LCR:
*((uint32_t *) arg) = REG_READ(UART_LCR);
break;
case IO_UART_SET_DLx:
/* 16 bit divisor --> DLL (lower 8) and DLH (upper 8) registers */
/* set LDAB bit for DLx register access, first */
val = REG_READ(UART_LCR);
REG_WRITE(UART_LCR, (val | (0x1 << 7)));
REG_WRITE(UART_DLL, (*((uint32_t *) arg) & 0x00ff));
REG_WRITE(UART_DLH, ((*((uint32_t *) arg) & 0xff00) >> 8));
REG_WRITE(UART_LCR, val);
break;
case IO_UART_GET_DLx:
/* set LDAB bit for DLx register access, first */
val = REG_READ(UART_LCR);
REG_WRITE(UART_LCR, (val | (0x1 << 7)));
*((uint32_t *) arg) =
(REG_READ(UART_DLL) | (REG_READ(UART_DLH) << 8));
REG_WRITE(UART_LCR, val);
break;
case IO_UART_SET_RX_THRESHOLD:
/* precondition: can only be called for dev->fifo_depth != 0 */
val = *((uint32_t *) arg);
dev->fcr_mirror = (dev->fcr_mirror & ~0xC) | (val << 2);
REG_WRITE(UART_FCR, ((dev->fcr_mirror << 4) | 0x01));
if (val == 0) {
dev->rx_threshold = 1;
} else if (val == 1) {
dev->rx_threshold = dev->fifo_depth >> 2;
} else if (val == 2) {
dev->rx_threshold = dev->fifo_depth >> 1;
} else if (val == 3) {
dev->rx_threshold = dev->fifo_depth - 2;
}
break;
case IO_UART_SET_TX_THRESHOLD:
/* precondition: can only be called for dev->fifo_depth != 0 */
val = *((uint32_t *) arg);
dev->fcr_mirror = (dev->fcr_mirror & ~0x3) | val;
REG_WRITE(UART_FCR, ((dev->fcr_mirror << 4) | 0x01));
if (val == 0) {
dev->tx_threshold = 0;
} else if (val == 1) {
dev->tx_threshold = 2;
} else if (val == 2) {
dev->tx_threshold = dev->fifo_depth >> 2;
} else if (val == 3) {
dev->tx_threshold = dev->fifo_depth >> 1;
}
break;
case IO_UART_SET_FLOW_CONTROL:
if ((uint32_t) (*((uint32_t *) arg)) == 1) {
// Enable Flow Control
dev->flow_control = FLOW_CONTROL_ON; // Use software implementation of CTS/RTS control
val = REG_READ(UART_IER) | 0x08;
REG_WRITE(UART_IER, val); // Enable modem status interrupt
val = REG_READ(UART_MSR);
if (val & 0x10) {
dev->nCTS_state = nCTS_LOW;
} else {
dev->nCTS_state = nCTS_HIGH;
}
} else {
// Diable Flow Control
dev->flow_control = FLOW_CONTROL_OFF;
val = REG_READ(UART_IER) & ~0x08;
REG_WRITE(UART_IER, val); // Disable modem status interrupt
}
break;
default:
break;
}
}
static void uart_isr_proc(uint32_t dev_id)
{
uart_info_pt dev = uart_handles[dev_id];
uint32_t intid = 0;
uint32_t cnt = 0;
uint32_t h = 0;
volatile uint32_t val = 0;
intid = REG_READ(UART_IIR) & 0x0f;
/* workaround for break detect: break interrupt may have been cleared by DMAC reading from rxfifo... */
if (intid == 0x1) { /* break detect + dma: copy source from while loop */
/* line break detected; complete read immediately */
#ifdef __Xdmac
if (dev->dmatxchanid == DMA_NONE) {
#endif
*(dev->p_rxsize) = dev->rx_count;
REG_READ(UART_RBR);
#ifdef __Xdmac
} else {
_dma_chan_enable((0x1 << dev->dmarxchanid), 0);
if (dev->dmarxchanid < DMAC_MEM_CHAN_CNT) {
_dma_chan_desc_get_ctrl(dev->dmarxchanid, &val);
} else {
_dma_chan_desc_aux_get_ctrl(dev->dmarxchanid, &val);
}
*(dev->p_rxsize) = dev->rx_count - 1 - ((val >> 8) & 0x1fff);
*(dev->p_rxsize) -= 1;
}
#endif
/* disable (ERBFI and) ELSI interrupt */
val = REG_READ(UART_IER) & ~0x5;
REG_WRITE(UART_IER, val);
if (dev->fifo_depth != 0) { /* restore threshold to user defined value */
REG_WRITE(UART_FCR, ((dev->fcr_mirror << 4) | 0x01));
}
/* call user callback function, if any */
if (dev->rx_cb != 0) {
dev->rx_cb(dev_id);
}
}
while (intid != 0x1) {
switch (intid) {
case 0x2:
{ /* tx empty */
if (dev->tx_data == NULL) {
if (dev->tx_cb != 0) {
dev->tx_cb(dev_id);
} else {
val = REG_READ(UART_IER) & ~0x82;
REG_WRITE(UART_IER, val);
}
} else {
if (dev->tx_count == dev->tx_size) { /* disable ETBEI interrupt (and disable threshold interrupt IER[7]) */
val = REG_READ(UART_IER) & ~0x82;
REG_WRITE(UART_IER, val);
/* call user callback function, if any */
if (dev->tx_cb != 0) {
dev->tx_cb(dev_id);
}
dev->tx_size = 0; // indicates no TX pending
} else {
/* write next bytes to fifo (if any) */
cnt = dev->tx_size - dev->tx_count;
if (dev->fifo_depth == 0) { /* fifos are not available */
cnt = 1;
} else if (cnt > dev->fifo_depth) { /* fifos enabled (and by definition != FIFO_NONE) */
cnt = dev->fifo_depth;
}
if (REG_READ(UART_IER) & 0x80) { /* if IER[7] is set, threshold shall be taken into account */
if (cnt > (dev->fifo_depth - dev->tx_threshold)) {
cnt = dev->fifo_depth - dev->tx_threshold;
}
}
for (h = 0; h != cnt; h++) {
REG_WRITE(UART_THR,
(dev->tx_data[dev->tx_count++]));
}
}
}
break;
}
case 0x4:
{ /* rx data available; at least one, more is uncertain */
if (dev->rx_data == NULL) {
if (dev->rx_cb != 0) {
dev->rx_cb(dev_id);
} else {
REG_READ(UART_RBR);
}
} else {
if (dev->fifo_depth == 0) {
dev->rx_data[dev->rx_count++] = REG_READ(UART_RBR);
} else {
cnt = dev->rx_size - dev->rx_count;
if (cnt < dev->rx_threshold) {
dev->rx_data[dev->rx_count++] = REG_READ(UART_RBR);
} else {
for (h = 0; h != dev->rx_threshold; h++) {
dev->rx_data[dev->rx_count++] =
REG_READ(UART_RBR);
}
cnt -= dev->rx_threshold;
if (cnt < dev->rx_threshold) {
/* temporary reset the rx_threshold to 1 */
REG_WRITE(UART_FCR,
(((dev->
fcr_mirror & ~0xC) << 4) | 0x01));
}
}
}
if (dev->rx_count == dev->rx_size) { /* disable ERBFI and ELSI interrupt */
val = REG_READ(UART_IER) & ~0x5;
REG_WRITE(UART_IER, val);
if (dev->fifo_depth != 0) { /* restore threshold to user defined value */
REG_WRITE(UART_FCR,
((dev->fcr_mirror << 4) | 0x01));
}
/* call user callback function, if any */
if (dev->rx_cb != 0) {
dev->rx_cb(dev_id);
}
}
}
break;
}
case 0x0: // Modem control status
{
val = REG_READ(UART_MSR);
if ((val & 0x10) != 0) {
dev->nCTS_state = nCTS_LOW;
// If there is a data buffer, it is time to start sending - nCTS turns low
if (dev->tx_size > 0) {
#ifdef __Xdmac
if (dev->dmatxchanid == DMA_NONE) {
#endif
/* enable ETBEI interrupt - starting TX */
val = REG_READ(UART_IER) | 0x2;
REG_WRITE(UART_IER, val);
#ifdef __Xdmac
} else {
_dma_chan_enable((0x1 << dev->dmatxchanid), 1); // !!!!!
}
#endif
}
} else {
// nCTS was switched high back
dev->nCTS_state = nCTS_HIGH;
}
break;
}
case 0x6:
{
val = REG_READ(UART_LSR);
if (val & (0x1 << 4)) {
/* line break detected; complete read immediately */
#ifdef __Xdmac
if (dev->dmatxchanid == DMA_NONE) {
#endif
*(dev->p_rxsize) = dev->rx_count;
REG_READ(UART_RBR);
#ifdef __Xdmac
} else {
_dma_chan_enable((0x1 << dev->dmarxchanid), 0);
if (dev->dmarxchanid < DMAC_MEM_CHAN_CNT) {
_dma_chan_desc_get_ctrl(dev->dmarxchanid,
&val);
} else {
_dma_chan_desc_aux_get_ctrl(dev->dmarxchanid,
&val);
}
*(dev->p_rxsize) =
dev->rx_count - 1 - ((val >> 8) & 0x1fff);
*(dev->p_rxsize) -= 1;
}
#endif
/* disable (ERBFI and) ELSI interrupt */
val = REG_READ(UART_IER) & ~0x5;
REG_WRITE(UART_IER, val);
if (dev->fifo_depth != 0) { /* restore threshold to user defined value */
REG_WRITE(UART_FCR,
((dev->fcr_mirror << 4) | 0x01));
}
/* call user callback function, if any */
if (dev->rx_cb != 0) {
dev->rx_cb(dev_id);
}
}
break;
}
case 0x7:
{
val = REG_READ(UART_USR);// update IIR busy status by read Uart Status Register
break;
}
default:
{ /* something wrong; at least, disable interrupts */
REG_WRITE(UART_IER, 0x0);
if (dev->err_cb != 0) {
dev->err_cb(dev_id);
}
break;
}
}
intid = REG_READ(UART_IIR) & 0x0f;
}
}
static void uart_dmatx_isr_proc(uint32_t dev_id)
{
#ifdef __Xdmac
uart_info_pt dev = uart_handles[dev_id];
uint32_t cnt = 0;
volatile uint32_t val = 0;
if (dev->tx_count == dev->tx_size) {
/* DMA TX xfer done */
_dma_chan_enable((0x1 << dev->dmatxchanid), 0);
_dma_int_clear((0x1 << dev->dmatxchanid));
/* enable ETBEI interrupt, to detect FIFO empty for end of tx */
val = REG_READ(UART_IER) | 0x2;
REG_WRITE(UART_IER, val);
} else {
/* clear DMA interrupt */
_dma_int_clear((0x1 << dev->dmatxchanid));
if (dev->fifo_depth == 0) { /* fifos are not available */
cnt = 1;
} else {
cnt = dev->fifo_depth - dev->tx_threshold;
}
create_dma_descriptor_tx(dev, cnt, dev->dmatxidx);
dev->dmatxidx = 4 - dev->dmatxidx;
}
#endif
}
static void uart_dmarx_isr_proc(uint32_t dev_id)
{
#ifdef __Xdmac
uart_info_pt dev = uart_handles[dev_id];
uint32_t val = 0;
if (dev->rx_count == dev->rx_size) {
/* Buffer transfer completed. Assert RTS line back if flow control is enabled */
if (dev->flow_control == FLOW_CONTROL_ON) {
val = REG_READ(UART_MCR) & ~0x2;
REG_WRITE(UART_MCR, val);
}
/* DMA RX xfer done */
_dma_chan_enable((0x1 << dev->dmarxchanid), 0);
_dma_int_clear((0x1 << dev->dmarxchanid));
/* call user callback function, if any */
if (dev->rx_cb != NULL) {
dev->rx_cb(dev_id);
}
} else {
/* clear DMA interrupt */
_dma_int_clear((0x1 << dev->dmarxchanid));
if (dev->fifo_depth == 0) { /* fifos are not available */
val = 1;
} else {
val = dev->rx_threshold;
}
create_dma_descriptor_rx(dev, val, dev->dmarxidx);
dev->dmarxidx = 4 - dev->dmarxidx;
}
#endif
}
#ifdef __Xdmac
#define UART_DMA_RX_END_CTRL (0xa0000015) /* am=b10, i=b1, dw/inc=b000, dtt=b10, r=b1, op=b01 */
#define UART_DMA_RX_CTRL (0x801fff17) /* am=b10, i=b0, size=h1fff, dw/inc=b000, dtt=b10, r=b1, op=b11 */
#define UART_DMA_RX_INT_CTRL (0xa01fff17) /* am=b10, i=b1, size=h1fff, dw/inc=b000, dtt=b10, r=b1, op=b11 */
#define UART_DMA_TX_END_CTRL (0x6000000d) /* am=b01, i=b1, dw/inc=b000, dtt=b01, r=b1, op=b01 */
#define UART_DMA_TX_CTRL (0x401fff0f) /* am=b01, i=b0, size=h1fff, dw/inc=b000, dtt=b01, r=b1, op=b11 */
#define UART_DMA_TX_INT_CTRL (0x601fff0f) /* am=b01, i=b1, size=h1fff, dw/inc=b000, dtt=b01, r=b1, op=b11 */
#define UART_DMA_CTRL_SIZE_POS (8)
#define UART_DMA_CTRL_XFER_POS (21)
/* use maximum block size of 4kB per DMA transfer */
static void create_dma_descriptor_rx(uart_info_pt dev, uint32_t burst,
uint8_t idx)
{
dev->dmarxdescriptor[idx + 0] = (burst << UART_DMA_CTRL_XFER_POS);
if ((dev->rx_size - dev->rx_count) <= 8 * 1024) {
dev->dmarxdescriptor[idx + 0] |=
UART_DMA_RX_END_CTRL | (((dev->rx_size - dev->rx_count) - 1) <<
UART_DMA_CTRL_SIZE_POS);
dev->rx_count = dev->rx_size;
} else {
dev->dmarxdescriptor[idx + 0] |=
((dev->rx_size - dev->rx_count) <=
2 * 8 * 1024 ? UART_DMA_RX_CTRL : UART_DMA_RX_INT_CTRL);
dev->rx_count += 8 * 1024;
}
dev->dmarxdescriptor[idx + 2] =
(uint32_t) dev->rx_data + (dev->rx_count - 1);
}
static void create_dma_descriptor_tx(uart_info_pt dev, uint32_t burst,
uint8_t idx)
{
dev->dmatxdescriptor[idx + 0] = (burst << UART_DMA_CTRL_XFER_POS);
if ((dev->tx_size - dev->tx_count) <= 8 * 1024) {
dev->dmatxdescriptor[idx + 0] |=
UART_DMA_TX_END_CTRL | (((dev->tx_size - dev->tx_count) - 1) <<
UART_DMA_CTRL_SIZE_POS);
dev->tx_count = dev->tx_size;
} else {
dev->dmatxdescriptor[idx + 0] |=
((dev->tx_size - dev->tx_count) <=
2 * 8 * 1024 ? UART_DMA_TX_CTRL : UART_DMA_TX_INT_CTRL);
dev->tx_count += 8 * 1024;
}
dev->dmatxdescriptor[idx + 1] =
(uint32_t) dev->tx_data + (dev->tx_count - 1);
}
#endif
#endif

View File

@@ -1,119 +0,0 @@
/* ------------------------------------------
* Copyright (c) 2018, 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.
*
--------------------------------------------- */
// ADC088S022 is ADC on EMSDP board
#include "embARC_toolchain.h"
#include "embARC_error.h"
#include "board.h"
// #define DBG_MORE
#include "embARC_debug.h"
#include "adc088s022.h"
#define ADC_CHECK_EXP_NORTN(EXPR) CHECK_EXP_NOERCD(EXPR, error_exit)
/**
* @brief Initialize adc088s022
* @param[in] obj adc088s022 object
* @retval E_OK Initialize adc088s022 successfully
* @retval !E_OK Initialize adc088s022 failed
*/
int32_t adc088s022_adc_init(ADC088S022_DEF_PTR obj)
{
int32_t ercd = E_OK;
DEV_SPI_PTR spi_obj = spi_get_dev(obj->dev_id);
dbg_printf(DBG_MORE_INFO, "[%s]%d: spi_obj 0x%x -> 0x%x\r\n", __FUNCTION__, __LINE__, spi_obj, *spi_obj);
ADC_CHECK_EXP_NORTN(spi_obj != NULL);
ercd = spi_obj->spi_open(DEV_MASTER_MODE, BOARD_ADC_SPI_HZ);
if ((ercd == E_OPNED) || (ercd == E_OK)) {
ercd = spi_obj->spi_control(SPI_CMD_SET_CLK_MODE, CONV2VOID(SPI_CLK_MODE_0));
}
error_exit:
return ercd;
}
/**
* @brief Deinitialize adc088s022
* @param[in] obj adc088s022 object
* @retval E_OK Deinitialize adc088s022 successfully
* @retval !E_OK Deinitialize adc088s022 failed
*/
int32_t adc088s022_adc_deinit(ADC088S022_DEF_PTR obj)
{
int32_t ercd = E_OK;
DEV_SPI_PTR spi_obj = spi_get_dev(obj->dev_id);
ercd = spi_obj->spi_close();
return ercd;
}
/**
* @brief Read adc088s022 channel
* @param[in] obj adc088s022 object
* @param[out] val Pointer to the return value (Unit is mV)
* @param[in] channel ADC channel
* @retval E_OK Read adc088s022 channel successfully
* @retval !E_OK Read adc088s022 channel failed
*/
int32_t adc088s022_adc_read(ADC088S022_DEF_PTR obj, float *val, int8_t channel)
{
int32_t ercd = E_OK;
DEV_SPI_PTR spi_obj = spi_get_dev(obj->dev_id);
dbg_printf(DBG_MORE_INFO, "[%s]%d: spi_obj 0x%x -> 0x%x\r\n", __FUNCTION__, __LINE__, spi_obj, *spi_obj);
ADC_CHECK_EXP_NORTN(spi_obj != NULL);
uint8_t adc_value = 0;
uint8_t spi_buffer_rx[2];
uint8_t spi_buffer_tx[2];
DEV_SPI_TRANSFER spi_xfer;
/* Master and Slave transmit */
DEV_SPI_XFER_SET_TXBUF(&spi_xfer, spi_buffer_tx, 0, 2);
DEV_SPI_XFER_SET_RXBUF(&spi_xfer, spi_buffer_rx, 0, 2);
DEV_SPI_XFER_SET_NEXT(&spi_xfer, NULL);
spi_buffer_tx[1] = ((channel & 0x07) << 3); // Select channel
ercd = spi_obj->spi_control(SPI_CMD_MST_SEL_DEV, CONV2VOID(0));
ercd = spi_obj->spi_control(SPI_CMD_TRANSFER_POLLING, CONV2VOID(&spi_xfer));
// Read it again to have valid number (otherwise you might get value from previous channel)
ercd = spi_obj->spi_control(SPI_CMD_TRANSFER_POLLING, CONV2VOID(&spi_xfer));
ercd = spi_obj->spi_control(SPI_CMD_MST_DSEL_DEV, CONV2VOID(0));
adc_value = (spi_buffer_rx[1] << 4) | (spi_buffer_rx[0] >> 4);
dbg_printf(DBG_MORE_INFO, "ADC-Channel(%d) = %d (0x%x)\r\n", channel, adc_value, adc_value);
*val = adc_value * ADC_REF_VDD / 256.0; // adc088s022 is an 8-bit ADC
error_exit:
return ercd;
}

View File

@@ -1,68 +0,0 @@
/* ------------------------------------------
* Copyright (c) 2018, Synopsys, Inc. All rights reserved.
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
* 1) Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2) Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
* 3) Neither the name of the Synopsys, Inc., nor the names of its contributors may
* be used to endorse or promote products derived from this software without
* specific prior written permission.
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
--------------------------------------------- */
#ifndef H_ADC088S022
#define H_ADC088S022
// ADC088S022 (a low-power, eight-channel. 23• Eight Input Channels. CMOS 8-bit analog-to-digital converter) is on EMSDP board
#define ADC_REF_VDD 3300 /*< power supply voltage is 3300mV, used as V_ref*/
#define ADC_FCLK_MIN 800000 // 0.8MHz
#define ADC_FLCK_MAX 3200000 // 3.2MHz
#define EMSDP_ADC_SPI_ID DFSS_SPI_2_ID
#define BOARD_ADC_SPI_HZ 1000000 // 1.0MHz
#if BOARD_ADC_SPI_HZ < ADC_FCLK_MIN || BOARD_ADC_SPI_HZ > ADC_FLCK_MAX
#error "BOARD_ADC_SPI_HZ should be within range of [ADC_FCLK_MIN, ADC_FLCK_MAX]"
#endif
#ifdef __cplusplus
extern "C" {
#endif
/** ADC088S022 object type */
typedef struct {
uint32_t dev_id;
} ADC088S022_DEF, *ADC088S022_DEF_PTR;
#define ADC088S022_DEFINE(NAME, DEVICE_ID) \
ADC088S022_DEF __ ## NAME = { \
.dev_id = DEVICE_ID, \
}; \
ADC088S022_DEF_PTR NAME = &__ ## NAME
extern int32_t adc088s022_adc_init(ADC088S022_DEF_PTR obj);
extern int32_t adc088s022_adc_deinit(ADC088S022_DEF_PTR obj);
extern int32_t adc088s022_adc_read(ADC088S022_DEF_PTR obj, float *val, int8_t channel);
#ifdef __cplusplus
}
#endif
#endif /* H_ADC088S022 */

View File

@@ -1,2 +0,0 @@
DEV_CSRCDIR += $(EMBARC_ROOT)/device/peripheral/adc/adc088s022
DEV_INCDIR += $(EMBARC_ROOT)/device/peripheral/adc/adc088s022

View File

@@ -1,728 +0,0 @@
/* ------------------------------------------
* Copyright (c) 2018, 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.
*
--------------------------------------------- */
#include "embARC.h"
#include "embARC_toolchain.h"
#include "embARC_error.h"
#include "board.h"
#include "max9880a.h"
#define DBG_LESS
#include "embARC_debug.h"
#define MAX9880A_CHECK_EXP(EXPR, ERROR_CODE) CHECK_EXP(EXPR, ercd, ERROR_CODE, error_exit)
// Register names
typedef enum {
MAX9880A_STATUS = 0x00, // RO 0x00
MAX9880A_JACKSTATUS, // RO 0x01
MAX9880A_AUXHIGH, // RO 0x02
MAX9880A_AUXLOW, // RO 0x03
MAX9880A_INTERRUPT_ENABLE, // RW 0x04
MAX9880A_SYSTEM_CLOCK, // RW 0x05
// DAI1-Clock Control
MAX9880A_DAI1_STEREO_AUDIO_CLK_CTRL_HIGH, // RW 0x06
MAX9880A_DAI1_STEREO_AUDIO_CLK_CTRL_LOW, // RW 0x07
// DAI1-Configuration
MAX9880A_DAI1_INTERFACE_MODE_A, // RW 0x08
MAX9880A_DAI1_INTERFACE_MODE_B, // RW 0x09
MAX9880A_DAI1_TIME_DIVISION_MUL, // RW 0x0A
// DAI2-Clock Control
MAX9880A_DAI2_STEREO_AUDIO_CLK_CTRL_HIGH, // RW 0x0B
MAX9880A_DAI2_STEREO_AUDIO_CLK_CTRL_LOW, // RW 0x0C
// DAI2-Configuration
MAX9880A_DAI2_INTERFACE_MODE_A, // RW 0x0D
MAX9880A_DAI2_INTERFACE_MODE_B, // RW 0x0E
MAX9880A_DAI2_TIME_DIVISION_MUL, // RW 0x0F
// Digital Mixers
MAX9880A_DAC_LR_MIXER, // RW 0x10
// Digital Filtering
MAX9880A_CODEC_FILTERS, // RW 0x11
// SPDM Outputs
MAX9880A_SPDM_CONFIGURATIONS, // RW 0x12
MAX9880A_SPDM_INPUT, // RW 0x13
MAX9880A_REV_ID, // RO 0x14
// LEVEL control
MAX9880A_SIDETONE, // RW 0x15
MAX9880A_STEREO_DAC_LEVEL, // RW 0x16
MAX9880A_VOICE_DAC_LEVEL, // RW 0x17
MAX9880A_LEFT_ADC_LEVEL, // RW 0x18
MAX9880A_RIGHT_ADC_LEVEL, // RW 0x19
MAX9880A_LEFT_LINE_INPUT_LEVEL, // RW 0x1A
MAX9880A_RIGHT_LINE_INPUT_LEVEL, // RW 0x1B
MAX9880A_LEFT_VOLUME_CTRL, // RW 0x1C
MAX9880A_RIGHT_VOLUME_CTRL, // RW 0x1D
MAX9880A_LEFT_LINE_OUTPUT_LEVEL, // RW 0x1E
MAX9880A_RIGHT_LINE_OUTPUT_LEVEL, // RW 0x1F
MAX9880A_LEFT_MIC_GAIN, // RW 0x20
MAX9880A_RIGHT_MIC_GAIN, // RW 0x21
// Configuration
MAX9880A_INPUT, // RW 0x22
MAX9880A_MICROPHONE, // RW 0x23
MAX9880A_MODE, // RW 0x24
MAX9880A_JACK_DETECT, // RW 0x25
// Power Management
MAX9880A_ENABLE, // RW 0x26
MAX9880A_SYSTEM_SHUTDOWN, // RW 0x27
MAX9880A_REVISION_ID = 0xFF, // RO 0xFF
} max9880a_reg_t;
typedef struct max9880a_settings {
max9880a_reg_t reg;
uint8_t val;
} max9880a_settings_t;
/******************************************************************************/
/*********** MAX9880A Configs **************************************/
/******************************************************************************/
/**
* MAX9880A_I2SIN_LINEOUT_13MHZ
*
* Playback: I2S In -> LineOut, Stereo 16Bit I2S, Fs=16 Khz (LRclk=32Khz)
*
* Measured with scope:
* => I2S clk from FPGA-HSDK to MAX: 512 KHz, divider is 48. (24.567 / 48 = 512 KHz).
* => I2S ws from FPGA-HSDK to MAX: 16 KHz.
* => I2S data from FPGA-HSDK to MAX: 16 bit
*
* => MCLK on MAX9880 board is not from FPGA-HSDK but a on board Chrystal of 13.00 MHz.
*/
const max9880a_settings_t settings_i2sin_lineout_13mhz[] =
{
{ MAX9880A_SYSTEM_SHUTDOWN, 0x04 }, // 0x27,
{ MAX9880A_SYSTEM_CLOCK, 0x10 }, // 0x05, MCLK between 10-20 Mhz (PCLK=MCLK)
// For recording (S1 pins are mapped on DAI1)
{ MAX9880A_DAI1_STEREO_AUDIO_CLK_CTRL_HIGH, 0x9E }, // 0x06, PLL=enabled, Ni=0x1E3F, DAI1 for LineIn -> I2S out, See table 6 datasheet (LRCLK=16 KHz PCLK=13 MHz)
{ MAX9880A_DAI1_STEREO_AUDIO_CLK_CTRL_LOW, 0x3F }, // 0x07
{ MAX9880A_DAI1_INTERFACE_MODE_A, 0x10 }, // 0x08, Slave mode, Delay Mode
{ MAX9880A_DAI1_INTERFACE_MODE_B, 0x30 }, // 0x09, SEL1 = 0, Map S1 to DAI1
// For playback (S2 pins are mapped on DAI2)
{ MAX9880A_DAI2_STEREO_AUDIO_CLK_CTRL_HIGH, 0x9E }, // 0x0B, PLL=enabled, Ni=0x1E3F, DAI2 for I2S in -> LineOut, See table 6 datasheet (LRCLK=16 KHz PCLK=13 MHz)
{ MAX9880A_DAI2_STEREO_AUDIO_CLK_CTRL_LOW, 0x3F }, // 0x0C
{ MAX9880A_DAI2_INTERFACE_MODE_A, 0x10 }, // 0x0D, Slave mode, Delay Mode, 16BitI2S
{ MAX9880A_DAI2_INTERFACE_MODE_B, 0x50 }, // 0x0E, SEL2 = 1, Map S2 to DAI2
{ MAX9880A_DAC_LR_MIXER, 0x21 }, // 0x10, DAi2 left channel, DAi2 right channel (audio out)
{ MAX9880A_CODEC_FILTERS, 0x80 }, // 0x11, select music filters
{ MAX9880A_LEFT_ADC_LEVEL, 0x0D }, // 0x18, Gain 0dB, Gain -10dB
{ MAX9880A_RIGHT_ADC_LEVEL, 0x0D }, // 0x19, Gain 0dB, Gain -10dB
{ MAX9880A_LEFT_LINE_INPUT_LEVEL, 0x0C }, // 0x1A, Gain 0dB
{ MAX9880A_RIGHT_LINE_INPUT_LEVEL, 0x0C }, // 0x1B, Gain 0dB
{ MAX9880A_LEFT_VOLUME_CTRL, 0x0C }, // 0x1C, Gain 0dB
{ MAX9880A_RIGHT_VOLUME_CTRL, 0x0C }, // 0x1D, Gain 0dB
{ MAX9880A_LEFT_LINE_OUTPUT_LEVEL, 0x00 }, // 0x1E, unmuted, Gain 0dB
{ MAX9880A_RIGHT_LINE_OUTPUT_LEVEL, 0x00 }, // 0x1F, unmuted, Gain 0dB
{ MAX9880A_INPUT, 0x00 }, // 0x22, No input selected
{ MAX9880A_ENABLE, 0x3C }, // 0x26, LineOut-Enable, LineIn-Disable, Left/Right DAC enabled
{ MAX9880A_SYSTEM_SHUTDOWN, 0x80 }, // 0x27, Power On, Mclk to clk prescaler, disable internal clk osc
};
#define SETTINGS_I2SIN_LINEOUT_13MHZ_LENGTH (sizeof(settings_i2sin_lineout_13mhz) / sizeof(settings_i2sin_lineout_13mhz[0]))
/**
* MAX9880A_LINEIN_I2SOUT_13MHZ
*
* Recording: LineIn -> I2S out, Stereo 16Bit I2S, Fs=16 Khz (LRclk=32Khz)
*
* Measured with scope:
* => I2S clk from HSDK to MAX: 512 KHz, divider is 48. (24.567 / 48 = 512 KHz).
* => I2S ws from HSDK to MAX: 16 KHz.
*
* => MCLK on MAX9880 board is not from FPGA-HSDK but a on board Chrystal of 13.00 MHz.
*/
const max9880a_settings_t settings_linein_i2sout_13mhz[] =
{
{ MAX9880A_SYSTEM_SHUTDOWN, 0x04 }, // 0x27
{ MAX9880A_SYSTEM_CLOCK, 0x10 }, // 0x05, MCLK between 10-20 Mhz (PCLK=MCLK)
// For recording (S1 pins are mapped on DAI1)
{ MAX9880A_DAI1_STEREO_AUDIO_CLK_CTRL_HIGH, 0x9E }, // 0x06, PLL=enabled, Ni=0x1E3F, DAI1 for LineIn -> I2S out, See table 6 datasheet (LRCLK=16 KHz PCLK=13 MHz)
{ MAX9880A_DAI1_STEREO_AUDIO_CLK_CTRL_LOW, 0x3F }, // 0x07
{ MAX9880A_DAI1_INTERFACE_MODE_A, 0x10 }, // 0x08, Slave mode, Delay Mode
{ MAX9880A_DAI1_INTERFACE_MODE_B, 0x30 }, // 0x09, SEL1 = 0, Map S1 to DAI1
// For playback (S2 pins are mapped on DAI2)
{ MAX9880A_DAI2_STEREO_AUDIO_CLK_CTRL_HIGH, 0x9E }, // 0x0B, PLL=enabled, Ni=0x1E3F, DAI2 for I2S in -> LineOut, See table 6 datasheet (LRCLK=16 KHz PCLK=13 MHz)
{ MAX9880A_DAI2_STEREO_AUDIO_CLK_CTRL_LOW, 0x3F }, // 0x0C
{ MAX9880A_DAI2_INTERFACE_MODE_A, 0x10 }, // 0x0D, Slave mode, Delay Mode, 16BitI2S
{ MAX9880A_DAI2_INTERFACE_MODE_B, 0x50 }, // 0x0E, SEL2 = 1, Map S2 to DAI2
{ MAX9880A_DAC_LR_MIXER, 0x21 }, // 0x10, DAi2 left channel, DAi2 right channel (audio out)
{ MAX9880A_CODEC_FILTERS, 0x80 }, // 0x11, Select music filters
{ MAX9880A_LEFT_ADC_LEVEL, 0x0D }, // 0x18, Gain 0dB, Gain -10dB
{ MAX9880A_RIGHT_ADC_LEVEL, 0x0D }, // 0x19, Gain 0dB, Gain -10dB
{ MAX9880A_LEFT_LINE_INPUT_LEVEL, 0x0C }, // 0x1A, Gain 0dB
{ MAX9880A_RIGHT_LINE_INPUT_LEVEL, 0x0C }, // 0x1B, Gain 0dB
{ MAX9880A_LEFT_VOLUME_CTRL, 0x0C }, // 0x1C, Gain 0dB
{ MAX9880A_RIGHT_VOLUME_CTRL, 0x0C }, // 0x1D, Gain 0dB
{ MAX9880A_LEFT_LINE_OUTPUT_LEVEL, 0x40 }, // 0x1E, muted
{ MAX9880A_RIGHT_LINE_OUTPUT_LEVEL, 0x40 }, // 0x1F, muted
{ MAX9880A_INPUT, 0xA0 }, // 0x22, Left & Right Line input
{ MAX9880A_ENABLE, 0xC3 }, // 0x26, LineIn-Enable, LineOut-Disable, Left/Right ADC enabled
{ MAX9880A_SYSTEM_SHUTDOWN, 0x80 }, // 0x27, Power On, Mclk to clk prescaler, disable internal clk osc
};
#define SETTINGS_LINEIN_I2SOUT_13MHZ_LENGTH (sizeof(settings_linein_i2sout_13mhz) / sizeof(settings_linein_i2sout_13mhz[0]))
/**
* MAX9880A_I2SIN_LINEOUT_12DOT288MHZ
*
* Playback: I2S In -> LineOut, Stereo 16Bit I2S, Fs=16 Khz (LRclk=32Khz)
*
* Measured with scope:
* => I2S clk from FPGA-HSDK to MAX: 512 KHz, divider is 48. (24.567 / 48 = 512 KHz).
* => I2S ws from FPGA-HSDK to MAX: 16 KHz.
* => I2S data from FPGA-HSDK to MAX: 16 bit
*
* => MCLK disconnected, route 12.288 XTAL to clk-prescaler (JU12 on max9880a board)
*
* Difference with 13 Mhz settings above is "*" regs
*/
const max9880a_settings_t settings_i2sin_lineout_12_288mhz[] =
{
{ MAX9880A_SYSTEM_SHUTDOWN, 0x04 }, // 0x27,
{ MAX9880A_SYSTEM_CLOCK, 0x10 }, // 0x05, MCLK between 10-20 Mhz (PCLK=MCLK)
// For recording (S1 pins are mapped on DAI1)
{ MAX9880A_DAI1_STEREO_AUDIO_CLK_CTRL_HIGH, 0xA0 }, // 0x06*, PLL=enabled, Ni=0x2000, DAI1 for LineIn -> I2S out, See table 6 datasheet (LRCLK=16 KHz PCLK=12.288 MHz)
{ MAX9880A_DAI1_STEREO_AUDIO_CLK_CTRL_LOW, 0x00 }, // 0x07*
{ MAX9880A_DAI1_INTERFACE_MODE_A, 0x10 }, // 0x08, Slave mode, Delay Mode
{ MAX9880A_DAI1_INTERFACE_MODE_B, 0x30 }, // 0x09, SEL1 = 0, Map S1 to DAI1
// For playback (S2 pins are mapped on DAI2)
{ MAX9880A_DAI2_STEREO_AUDIO_CLK_CTRL_HIGH, 0xA0 }, // 0x0B*, PLL=enabled, Ni=0x2000, DAI2 for I2S in -> LineOut, See table 6 datasheet (LRCLK=16 KHz PCLK=12.288 MHz)
{ MAX9880A_DAI2_STEREO_AUDIO_CLK_CTRL_LOW, 0x00 }, // 0x0C*
{ MAX9880A_DAI2_INTERFACE_MODE_A, 0x10 }, // 0x0D, Slave mode, Delay Mode, 16BitI2S
{ MAX9880A_DAI2_INTERFACE_MODE_B, 0x50 }, // 0x0E, SEL2 = 1, Map S2 to DAI2
{ MAX9880A_DAC_LR_MIXER, 0x21 }, // 0x10, DAi2 left channel, DAi2 right channel (audio out)
{ MAX9880A_CODEC_FILTERS, 0x80 }, // 0x11, select music filters
{ MAX9880A_LEFT_ADC_LEVEL, 0x0D }, // 0x18, Gain 0dB, Gain -10dB
{ MAX9880A_RIGHT_ADC_LEVEL, 0x0D }, // 0x19, Gain 0dB, Gain -10dB
{ MAX9880A_LEFT_LINE_INPUT_LEVEL, 0x0C }, // 0x1A, Gain 0dB
{ MAX9880A_RIGHT_LINE_INPUT_LEVEL, 0x0C }, // 0x1B, Gain 0dB
{ MAX9880A_LEFT_VOLUME_CTRL, 0x0C }, // 0x1C, Gain 0dB
{ MAX9880A_RIGHT_VOLUME_CTRL, 0x0C }, // 0x1D, Gain 0dB
{ MAX9880A_LEFT_LINE_OUTPUT_LEVEL, 0x00 }, // 0x1E, unmuted, Gain 0dB
{ MAX9880A_RIGHT_LINE_OUTPUT_LEVEL, 0x00 }, // 0x1F, unmuted, Gain 0dB
{ MAX9880A_INPUT, 0x00 }, // 0x22, No input selected
{ MAX9880A_ENABLE, 0x3C }, // 0x26, LineOut-Enable, LineIn-Disable, Left/Right DAC enabled
{ MAX9880A_SYSTEM_SHUTDOWN, 0x88 }, // 0x27*, Power On, Xtal to clk-prescaler
};
#define SETTINGS_I2SIN_LINEOUT_12_288MHZ_LENGTH (sizeof(settings_i2sin_lineout_12_288mhz) / sizeof(settings_i2sin_lineout_12_288mhz[0]))
/**
* MAX9880A_LINEIN_I2SOUT_12DOT288MHZ
*
* Recording: LineIn -> I2S out, Stereo 16Bit I2S, Fs=16 Khz (LRclk=32Khz)
*
* Measured with scope:
* => I2S clk from FPGA-HSDK to MAX: 512 KHz, divider is 48. (24.567 / 48 = 512 KHz).
* => I2S ws from FPGA-HSDK to MAX: 16 KHz.
*
* => MCLK disconnected, route 12.288 XTAL to clk-prescaler
*
* Difference with 13 Mhz settings above is "*" regs
*/
const max9880a_settings_t settings_linein_i2sout_12_288mhz[] =
{
{ MAX9880A_SYSTEM_SHUTDOWN, 0x04 }, // 0x27
{ MAX9880A_SYSTEM_CLOCK, 0x10 }, // 0x05, MCLK between 10-20 Mhz (PCLK=MCLK)
// For recording (S1 pins are mapped on DAI1)
{ MAX9880A_DAI1_STEREO_AUDIO_CLK_CTRL_HIGH, 0xA0 }, // 0x06*, PLL=enabled, Ni=0x2000, DAI1 for LineIn -> I2S out, See table 6 datasheet (LRCLK=16 KHz PCLK=12.288 MHz)
{ MAX9880A_DAI1_STEREO_AUDIO_CLK_CTRL_LOW, 0x00 }, // 0x07*
{ MAX9880A_DAI1_INTERFACE_MODE_A, 0x10 }, // 0x08, Slave mode, Delay Mode
{ MAX9880A_DAI1_INTERFACE_MODE_B, 0x30 }, // 0x09, SEL1 = 0, Map S1 to DAI1
// For playback (S2 pins are mapped on DAI2)
{ MAX9880A_DAI2_STEREO_AUDIO_CLK_CTRL_HIGH, 0xA0 }, // 0x0B*, PLL=enabled, Ni=0x2000, DAI2 for I2S in -> LineOut, See table 6 datasheet (LRCLK=16 KHz PCLK=12.288 MHz)
{ MAX9880A_DAI2_STEREO_AUDIO_CLK_CTRL_LOW, 0x00 }, // 0x0C*
{ MAX9880A_DAI2_INTERFACE_MODE_A, 0x10 }, // 0x0D, Slave mode, Delay Mode, 16BitI2S
{ MAX9880A_DAI2_INTERFACE_MODE_B, 0x50 }, // 0x0E, SEL2 = 1, Map S2 to DAI2
{ MAX9880A_DAC_LR_MIXER, 0x21 }, // 0x10, DAi2 left channel, DAi2 right channel (audio out)
{ MAX9880A_CODEC_FILTERS, 0x80 }, // 0x11, Select music filters
{ MAX9880A_LEFT_ADC_LEVEL, 0x0D }, // 0x18, Gain 0dB, Gain -10dB
{ MAX9880A_RIGHT_ADC_LEVEL, 0x0D }, // 0x19, Gain 0dB, Gain -10dB
{ MAX9880A_LEFT_LINE_INPUT_LEVEL, 0x0C }, // 0x1A, Gain 0dB
{ MAX9880A_RIGHT_LINE_INPUT_LEVEL, 0x0C }, // 0x1B, Gain 0dB
{ MAX9880A_LEFT_VOLUME_CTRL, 0x0C }, // 0x1C, Gain 0dB
{ MAX9880A_RIGHT_VOLUME_CTRL, 0x0C }, // 0x1D, Gain 0dB
{ MAX9880A_LEFT_LINE_OUTPUT_LEVEL, 0x40 }, // 0x1E, muted
{ MAX9880A_RIGHT_LINE_OUTPUT_LEVEL, 0x40 }, // 0x1F, muted
{ MAX9880A_INPUT, 0xA0 }, // 0x22, Left & Right Line input
{ MAX9880A_ENABLE, 0xC3 }, // 0x26, LineIn-Enable, LineOut-Disable, Left/Right ADC enabled
{ MAX9880A_SYSTEM_SHUTDOWN, 0x88 }, // 0x27*, Power On, Xtal to clk-prescaler
};
#define SETTINGS_LINEIN_I2SOUT_12_288MHZ_LENGTH (sizeof(settings_linein_i2sout_12_288mhz) / sizeof(settings_linein_i2sout_12_288mhz[0]))
/**
* MAX9880A_I2SIN_LINEOUT_24DOT567MHZ
*
* Playback: I2S In -> LineOut, Stereo 16Bit I2S, Fs=16 Khz (LRclk=32Khz)
*
* Measured with scope:
* => I2S clk from FPGA-HSDK to MAX: 512 KHz, divider is 48. (24.567 / 48 = 512 KHz).
* => I2S ws from FPGA-HSDK to MAX: 16 KHz.
* => I2S data from FPGA-HSDK to MAX: 16 bit
*
* => MCLK from FPGA-HSDK of 24.567 MHz
*
* Difference with 13 Mhz settings above is "*" regs
*/
const max9880a_settings_t settings_i2sin_lineout_24_567mhz[] =
{
{ MAX9880A_SYSTEM_SHUTDOWN, 0x04 }, // 0x27,
{ MAX9880A_SYSTEM_CLOCK, 0x20 }, // 0x05*, MCLK between 20-40 Mhz (PCLK=MCLK/2)
// For recording (S1 pins are mapped on DAI1)
{ MAX9880A_DAI1_STEREO_AUDIO_CLK_CTRL_HIGH, 0xA0 }, // 0x06*, PLL=enabled, Ni=0x2000, DAI1 for LineIn -> I2S out, See table 6 datasheet (LRCLK=16 KHz PCLK=12.288 MHz)
{ MAX9880A_DAI1_STEREO_AUDIO_CLK_CTRL_LOW, 0x00 }, // 0x07*
{ MAX9880A_DAI1_INTERFACE_MODE_A, 0x10 }, // 0x08, Slave mode, Delay Mode
{ MAX9880A_DAI1_INTERFACE_MODE_B, 0x30 }, // 0x09, SEL1 = 0, Map S1 to DAI1
// For playback (S2 pins are mapped on DAI2)
{ MAX9880A_DAI2_STEREO_AUDIO_CLK_CTRL_HIGH, 0xA0 }, // 0x0B*, PLL=enabled, Ni=0x2000, DAI2 for I2S in -> LineOut, See table 6 datasheet (LRCLK=16 KHz PCLK=12.288 MHz)
{ MAX9880A_DAI2_STEREO_AUDIO_CLK_CTRL_LOW, 0x00 }, // 0x0C*
{ MAX9880A_DAI2_INTERFACE_MODE_A, 0x10 }, // 0x0D, Slave mode, Delay Mode, 16BitI2S
{ MAX9880A_DAI2_INTERFACE_MODE_B, 0x50 }, // 0x0E, SEL2 = 1, Map S2 to DAI2
{ MAX9880A_DAC_LR_MIXER, 0x21 }, // 0x10, DAi2 left channel, DAi2 right channel (audio out)
{ MAX9880A_CODEC_FILTERS, 0x80 }, // 0x11, select music filters
{ MAX9880A_LEFT_ADC_LEVEL, 0x0D }, // 0x18, Gain 0dB, Gain -10dB
{ MAX9880A_RIGHT_ADC_LEVEL, 0x0D }, // 0x19, Gain 0dB, Gain -10dB
{ MAX9880A_LEFT_LINE_INPUT_LEVEL, 0x0C }, // 0x1A, Gain 0dB
{ MAX9880A_RIGHT_LINE_INPUT_LEVEL, 0x0C }, // 0x1B, Gain 0dB
{ MAX9880A_LEFT_VOLUME_CTRL, 0x0C }, // 0x1C, Gain 0dB
{ MAX9880A_RIGHT_VOLUME_CTRL, 0x0C }, // 0x1D, Gain 0dB
{ MAX9880A_LEFT_LINE_OUTPUT_LEVEL, 0x00 }, // 0x1E, unmuted, Gain 0dB
{ MAX9880A_RIGHT_LINE_OUTPUT_LEVEL, 0x00 }, // 0x1F, unmuted, Gain 0dB
{ MAX9880A_INPUT, 0x00 }, // 0x22, No input selected
{ MAX9880A_ENABLE, 0x3C }, // 0x26, LineOut-Enable, LineIn-Disable, Left/Right DAC enabled
{ MAX9880A_SYSTEM_SHUTDOWN, 0x80 }, // 0x27, Power On, Mclk to clk-prescaler
};
#define SETTINGS_I2SIN_LINEOUT_24_567MHZ_LENGTH (sizeof(settings_i2sin_lineout_24_567mhz) / sizeof(settings_i2sin_lineout_24_567mhz[0]))
/**
* MAX9880A_LINEIN_I2SOUT_24DOT567MHZ
*
* Recording: LineIn -> I2S out, Stereo 16Bit I2S, Fs=16 Khz (LRclk=32Khz)
*
* Measured with scope:
* => I2S clk from FPGA-HSDK to MAX: 512 KHz, divider is 48. (24.567 / 48 = 512 KHz).
* => I2S ws from FPGA-HSDK to MAX: 16 KHz.
*
* => MCLK from HSDK of 24.567 MHz
*
* Difference with 13 Mhz settings above is "*" regs
*/
const max9880a_settings_t settings_linein_i2sout_24_567mhz[] =
{
{ MAX9880A_SYSTEM_SHUTDOWN, 0x04 }, // 0x27
{ MAX9880A_SYSTEM_CLOCK, 0x20 }, // 0x05*, MCLK between 20-40 Mhz (PCLK=MCLK/2)
// For recording (S1 pins are mapped on DAI1)
{ MAX9880A_DAI1_STEREO_AUDIO_CLK_CTRL_HIGH, 0xA0 }, // 0x06*, PLL=enabled, Ni=0x2000, DAI1 for LineIn -> I2S out, See table 6 datasheet (LRCLK=16 KHz PCLK=12.288 MHz)
{ MAX9880A_DAI1_STEREO_AUDIO_CLK_CTRL_LOW, 0x00 }, // 0x07*
{ MAX9880A_DAI1_INTERFACE_MODE_A, 0x10 }, // 0x08, Slave mode, Delay Mode
{ MAX9880A_DAI1_INTERFACE_MODE_B, 0x30 }, // 0x09, SEL1 = 0, Map S1 to DAI1
// For playback (S2 pins are mapped on DAI2)
{ MAX9880A_DAI2_STEREO_AUDIO_CLK_CTRL_HIGH, 0xA0 }, // 0x0B*, PLL=enabled, Ni=0x2000, DAI2 for I2S in -> LineOut, See table 6 datasheet (LRCLK=16 KHz PCLK=12.288 MHz)
{ MAX9880A_DAI2_STEREO_AUDIO_CLK_CTRL_LOW, 0x00 }, // 0x0C*
{ MAX9880A_DAI2_INTERFACE_MODE_A, 0x10 }, // 0x0D, Slave mode, Delay Mode, 16BitI2S
{ MAX9880A_DAI2_INTERFACE_MODE_B, 0x50 }, // 0x0E, SEL2 = 1, Map S2 to DAI2
{ MAX9880A_DAC_LR_MIXER, 0x21 }, // 0x10, DAi2 left channel, DAi2 right channel (audio out)
{ MAX9880A_CODEC_FILTERS, 0x80 }, // 0x11, Select music filters
{ MAX9880A_LEFT_ADC_LEVEL, 0x0D }, // 0x18, Gain 0dB, Gain -10dB
{ MAX9880A_RIGHT_ADC_LEVEL, 0x0D }, // 0x19, Gain 0dB, Gain -10dB
{ MAX9880A_LEFT_LINE_INPUT_LEVEL, 0x0C }, // 0x1A, Gain 0dB
{ MAX9880A_RIGHT_LINE_INPUT_LEVEL, 0x0C }, // 0x1B, Gain 0dB
{ MAX9880A_LEFT_VOLUME_CTRL, 0x0C }, // 0x1C, Gain 0dB
{ MAX9880A_RIGHT_VOLUME_CTRL, 0x0C }, // 0x1D, Gain 0dB
{ MAX9880A_LEFT_LINE_OUTPUT_LEVEL, 0x40 }, // 0x1E, muted
{ MAX9880A_RIGHT_LINE_OUTPUT_LEVEL, 0x40 }, // 0x1F, muted
{ MAX9880A_INPUT, 0xA0 }, // 0x22, Left & Right Line input
{ MAX9880A_ENABLE, 0xC3 }, // 0x26, LineIn-Enable, LineOut-Disable, Left/Right ADC enabled
{ MAX9880A_SYSTEM_SHUTDOWN, 0x80 }, // 0x27, Power On, Mclk to clk-prescaler
};
#define SETTINGS_LINEIN_I2SOUT_24_567MHZ_LENGTH (sizeof(settings_linein_i2sout_24_567mhz) / sizeof(settings_linein_i2sout_24_567mhz[0]))
/**
* MAX9880A_DAI2_I2SIN_LINEOUT_24DOT567MHZ
*
* Playback: I2S In -> LineOut, Stereo 16Bit I2S, Fs=16 Khz (LRclk=32Khz)
* But now we have PLAYBACK on DAI2 (input I2S on S1 BCLKS1, LRCLKS1, SDINS1 from I2S-TX)
*
* Measured with scope:
* => I2S clk from IC-HSDK to MAX: 512 KHz, divider is 48. (24.567 / 48 = 512 KHz).
* => I2S ws from IC-HSDK to MAX: 16 KHz.
* => I2S data from IC-HSDK to MAX: 16 bit
*
* => MCLK from HSDK of 24.567 MHz
*
*/
const max9880a_settings_t settings_dai2_i2sin_lineout_24_567mhz[] =
{
{ MAX9880A_SYSTEM_SHUTDOWN, 0x04 }, // 0x27,
{ MAX9880A_SYSTEM_CLOCK, 0x20 }, // 0x05, MCLK between 20-40 Mhz (PCLK=MCLK/2)
// For recording (S2 pins are mapped on DAI1)
{ MAX9880A_DAI1_STEREO_AUDIO_CLK_CTRL_HIGH, 0xA0 }, // 0x06, PLL=enabled, Ni=0x2000, See table 6 datasheet (LRCLK=16 KHz PCLK=12.288 MHz)
{ MAX9880A_DAI1_STEREO_AUDIO_CLK_CTRL_LOW, 0x00 }, // 0x07
{ MAX9880A_DAI1_INTERFACE_MODE_A, 0x10 }, // 0x08, Slave mode, Delay Mode
{ MAX9880A_DAI1_INTERFACE_MODE_B, 0x50 }, // 0x09, SEL1 = 1, Map S1 to DAI2, SDIEN1=1, SDOEN1=0
// For playback (S1 pins are mapped on DAI2)
{ MAX9880A_DAI2_STEREO_AUDIO_CLK_CTRL_HIGH, 0xA0 }, // 0x0B, PLL=enabled, Ni=0x2000, See table 6 datasheet (LRCLK=16 KHz PCLK=12.288 MHz)
{ MAX9880A_DAI2_STEREO_AUDIO_CLK_CTRL_LOW, 0x00 }, // 0x0C
{ MAX9880A_DAI2_INTERFACE_MODE_A, 0x10 }, // 0x0D, Slave mode, Delay Mode, 16BitI2S
{ MAX9880A_DAI2_INTERFACE_MODE_B, 0x30 }, // 0x0E, SEL2 = 0, Map S2 to DAI1, SDIEN2=1, SDOEN2=1
{ MAX9880A_DAC_LR_MIXER, 0x21 }, // 0x10, DAi2 left channel, DAi2 right channel (i2s in)
{ MAX9880A_CODEC_FILTERS, 0x80 }, // 0x11, select music filters
{ MAX9880A_LEFT_ADC_LEVEL, 0x0D }, // 0x18, Gain 0dB, Gain -10dB
{ MAX9880A_RIGHT_ADC_LEVEL, 0x0D }, // 0x19, Gain 0dB, Gain -10dB
{ MAX9880A_LEFT_LINE_INPUT_LEVEL, 0x0C }, // 0x1A, Gain 0dB
{ MAX9880A_RIGHT_LINE_INPUT_LEVEL, 0x0C }, // 0x1B, Gain 0dB
{ MAX9880A_LEFT_VOLUME_CTRL, 0x0C }, // 0x1C, Gain 0dB
{ MAX9880A_RIGHT_VOLUME_CTRL, 0x0C }, // 0x1D, Gain 0dB
{ MAX9880A_LEFT_LINE_OUTPUT_LEVEL, 0x00 }, // 0x1E, unmuted, Gain 0dB
{ MAX9880A_RIGHT_LINE_OUTPUT_LEVEL, 0x00 }, // 0x1F, unmuted, Gain 0dB
{ MAX9880A_INPUT, 0x00 }, // 0x22, No input selected
{ MAX9880A_ENABLE, 0x3C }, // 0x26, LineOut-Enable, LineIn-Disable, Left/Right DAC enabled
{ MAX9880A_SYSTEM_SHUTDOWN, 0x80 }, // 0x27, Power On, Mclk to clk-prescaler
};
#define SETTINGS_DAI2_I2SIN_LINEOUT_24_567MHZ_LENGTH (sizeof(settings_dai2_i2sin_lineout_24_567mhz) / sizeof(settings_dai2_i2sin_lineout_24_567mhz[0]))
/**
* MAX9880A_LINEIN_DAI1_I2SOUT_24DOT567MHZ
*
* Recording: LineIn -> I2S out, Stereo 16Bit I2S, Fs=16 Khz (LRclk=32Khz)
* But now we have RECORDING on DAI1 (output I2S on S2 BCLKS2, LRCLKS2, SDOUTS2 to I2S-RX)
*
* Measured with scope:
* => I2S clk from IC-HSDK to MAX: 512 KHz, divider is 48. (24.567 / 48 = 512 KHz).
* => I2S ws from IC-HSDK to MAX: 16 KHz.
*
* => MCLK from IC-HSDK of 24.567 MHz
*/
const max9880a_settings_t settings_linein_dai1_i2sout_24_567mhz[] =
{
{ MAX9880A_SYSTEM_SHUTDOWN, 0x04 }, // 0x27
{ MAX9880A_SYSTEM_CLOCK, 0x20 }, // 0x05, MCLK between 20-40 Mhz (PCLK=MCLK/2)
// For recording (S2 pins are mapped on DAI1)
{ MAX9880A_DAI1_STEREO_AUDIO_CLK_CTRL_HIGH, 0xA0 }, // 0x06, PLL=enabled, Ni=0x2000, See table 6 datasheet (LRCLK=16 KHz PCLK=12.288 MHz)
{ MAX9880A_DAI1_STEREO_AUDIO_CLK_CTRL_LOW, 0x00 }, // 0x07
{ MAX9880A_DAI1_INTERFACE_MODE_A, 0x10 }, // 0x08, Slave mode, Delay Mode
{ MAX9880A_DAI1_INTERFACE_MODE_B, 0x50 }, // 0x09, SEL1 = 1, Map S1 to DAI2, SDIEN1=1, SDOEN1=0
// For playback (S1 pins are mapped on DAI2)
{ MAX9880A_DAI2_STEREO_AUDIO_CLK_CTRL_HIGH, 0xA0 }, // 0x0B, PLL=enabled, Ni=0x2000, See table 6 datasheet (LRCLK=16 KHz PCLK=12.288 MHz)
{ MAX9880A_DAI2_STEREO_AUDIO_CLK_CTRL_LOW, 0x00 }, // 0x0C
{ MAX9880A_DAI2_INTERFACE_MODE_A, 0x10 }, // 0x0D, Slave mode, Delay Mode, 16BitI2S
{ MAX9880A_DAI2_INTERFACE_MODE_B, 0x30 }, // 0x0E, SEL2 = 0, Map S2 to DAI1, SDIEN2=1, SDOEN2=1
{ MAX9880A_DAC_LR_MIXER, 0x84 }, // 0x10, DAi1 left channel, DAi1 right channel (i2s out)
{ MAX9880A_CODEC_FILTERS, 0x80 }, // 0x11, Select music filters
{ MAX9880A_LEFT_ADC_LEVEL, 0x0D }, // 0x18, Gain 0dB, Gain -10dB
{ MAX9880A_RIGHT_ADC_LEVEL, 0x0D }, // 0x19, Gain 0dB, Gain -10dB
{ MAX9880A_LEFT_LINE_INPUT_LEVEL, 0x0C }, // 0x1A, Gain 0dB
{ MAX9880A_RIGHT_LINE_INPUT_LEVEL, 0x0C }, // 0x1B, Gain 0dB
{ MAX9880A_LEFT_VOLUME_CTRL, 0x0C }, // 0x1C, Gain 0dB
{ MAX9880A_RIGHT_VOLUME_CTRL, 0x0C }, // 0x1D, Gain 0dB
{ MAX9880A_LEFT_LINE_OUTPUT_LEVEL, 0x40 }, // 0x1E, muted
{ MAX9880A_RIGHT_LINE_OUTPUT_LEVEL, 0x40 }, // 0x1F, muted
{ MAX9880A_INPUT, 0xA0 }, // 0x22, Left & Right Line input
{ MAX9880A_ENABLE, 0xC3 }, // 0x26, LineIn-Enable, LineOut-Disable, Left/Right ADC enabled
{ MAX9880A_SYSTEM_SHUTDOWN, 0x80 }, // 0x27, Power On, Mclk to clk-prescaler
};
#define SETTINGS_LINEIN_DAI1_I2SOUT_24_567MHZ_LENGTH (sizeof(settings_linein_dai1_i2sout_24_567mhz) / sizeof(settings_linein_dai1_i2sout_24_567mhz[0]))
/**
* MAX9880A_24DOT567MHZ
*
* Playback & Recording (both tables mixed)
*/
const max9880a_settings_t settings_24_567mhz[] =
{
{ MAX9880A_SYSTEM_SHUTDOWN, 0x04 }, // 0x27,
{ MAX9880A_SYSTEM_CLOCK, 0x20 }, // 0x05, MCLK between 20-40 Mhz (PCLK=MCLK/2)
// For recording (S2 pins are mapped on DAI1)
{ MAX9880A_DAI1_STEREO_AUDIO_CLK_CTRL_HIGH, 0xA0 }, // 0x06, PLL=enabled, Ni=0x2000, See table 6 datasheet (LRCLK=16 KHz PCLK=12.288 MHz)
{ MAX9880A_DAI1_STEREO_AUDIO_CLK_CTRL_LOW, 0x00 }, // 0x07
{ MAX9880A_DAI1_INTERFACE_MODE_A, 0x10 }, // 0x08, Slave mode, Delay Mode
{ MAX9880A_DAI1_INTERFACE_MODE_B, 0x50 }, // 0x09, SEL1 = 1, Map S1 to DAI2, SDIEN1=1, SDOEN1=0
// For playback (S1 pins are mapped on DAI2)
{ MAX9880A_DAI2_STEREO_AUDIO_CLK_CTRL_HIGH, 0xA0 }, // 0x0B, PLL=enabled, Ni=0x2000, See table 6 datasheet (LRCLK=16 KHz PCLK=12.288 MHz)
{ MAX9880A_DAI2_STEREO_AUDIO_CLK_CTRL_LOW, 0x00 }, // 0x0C
{ MAX9880A_DAI2_INTERFACE_MODE_A, 0x10 }, // 0x0D, Slave mode, Delay Mode, 16BitI2S
{ MAX9880A_DAI2_INTERFACE_MODE_B, 0x30 }, // 0x0E, SEL2 = 0, Map S2 to DAI1, SDIEN2=1, SDOEN2=1
{ MAX9880A_DAC_LR_MIXER, 0xA5 }, // 0x10, DAi2 left channel, DAi2 right channel (i2s in/out)
{ MAX9880A_CODEC_FILTERS, 0x80 }, // 0x11, select music filters
{ MAX9880A_LEFT_ADC_LEVEL, 0x0D }, // 0x18, Gain 0dB, Gain -10dB
{ MAX9880A_RIGHT_ADC_LEVEL, 0x0D }, // 0x19, Gain 0dB, Gain -10dB
{ MAX9880A_LEFT_LINE_INPUT_LEVEL, 0x0C }, // 0x1A, Gain 0dB
{ MAX9880A_RIGHT_LINE_INPUT_LEVEL, 0x0C }, // 0x1B, Gain 0dB
{ MAX9880A_LEFT_VOLUME_CTRL, 0x0C }, // 0x1C, Gain 0dB
{ MAX9880A_RIGHT_VOLUME_CTRL, 0x0C }, // 0x1D, Gain 0dB
{ MAX9880A_LEFT_LINE_OUTPUT_LEVEL, 0x00 }, // 0x1E, unmuted, Gain 0dB
{ MAX9880A_RIGHT_LINE_OUTPUT_LEVEL, 0x00 }, // 0x1F, unmuted, Gain 0dB
{ MAX9880A_INPUT, 0xA0 }, // 0x22, Left & Right Line input
{ MAX9880A_ENABLE, 0xFF }, // 0x26, LineOut-Enable, LineIn-Enable, Left/Right ADC/DAC enabled
{ MAX9880A_SYSTEM_SHUTDOWN, 0x80 }, // 0x27, Power On, Mclk to clk-prescaler
};
#define SETTINGS_24_567MHZ_LENGTH (sizeof(settings_24_567mhz) / sizeof(settings_24_567mhz[0]))
/******************************************************************************/
/*********** END of MAX9880A Configs ********************************/
/******************************************************************************/
// Max9880a register name list
typedef struct max9880a_reg_table {
char str[10];
max9880a_reg_t reg;
} max9880a_reg_table_t;
const max9880a_reg_table_t max9880a_reg_table[] =
{
{ "STS ", MAX9880A_STATUS },
{ "JACK STS ", MAX9880A_JACKSTATUS },
{ "AUX HIGH ", MAX9880A_AUXHIGH },
{ "AUX LOW ", MAX9880A_AUXLOW },
{ "INT ENA ", MAX9880A_INTERRUPT_ENABLE },
{ "SYS CLK ", MAX9880A_SYSTEM_CLOCK },
// DAI1-Clock Control
{ "DAI1 CLKH", MAX9880A_DAI1_STEREO_AUDIO_CLK_CTRL_HIGH },
{ "DAI1 CLKL", MAX9880A_DAI1_STEREO_AUDIO_CLK_CTRL_LOW },
// DAI1-Configuration
{ "INTMODE A", MAX9880A_DAI1_INTERFACE_MODE_A },
{ "INTMODE B", MAX9880A_DAI1_INTERFACE_MODE_B },
{ "TIME DIV ", MAX9880A_DAI1_TIME_DIVISION_MUL },
// DAI2-Clock Control
{ "DAI2 CLKH", MAX9880A_DAI2_STEREO_AUDIO_CLK_CTRL_HIGH },
{ "DAI2 CLKL", MAX9880A_DAI2_STEREO_AUDIO_CLK_CTRL_LOW },
// DAI2-Configuration
{ "INTMODE A", MAX9880A_DAI2_INTERFACE_MODE_A },
{ "INTMODE B", MAX9880A_DAI2_INTERFACE_MODE_B },
{ "TIME DIV ", MAX9880A_DAI2_TIME_DIVISION_MUL },
// Digital Mixers
{ "DAC-LRMIX", MAX9880A_DAC_LR_MIXER },
// Digital Filtering
{ "CODEC ", MAX9880A_CODEC_FILTERS },
// SPDM Outputs
{ "SPDM CONF", MAX9880A_SPDM_CONFIGURATIONS },
{ "SPDM INP ", MAX9880A_SPDM_INPUT },
{ "REV ID ", MAX9880A_REV_ID },
// LEVEL control
{ "SIDE TONE", MAX9880A_SIDETONE },
{ "STDAC LVL", MAX9880A_STEREO_DAC_LEVEL },
{ "V-DAC LVL", MAX9880A_VOICE_DAC_LEVEL },
{ "ADC LVL L", MAX9880A_LEFT_ADC_LEVEL },
{ "ADC LVL R", MAX9880A_RIGHT_ADC_LEVEL },
{ "LIINLVL L", MAX9880A_LEFT_LINE_INPUT_LEVEL },
{ "LIINLVL R", MAX9880A_RIGHT_LINE_INPUT_LEVEL },
{ "VOLCTRL L", MAX9880A_LEFT_VOLUME_CTRL },
{ "VOLCTRL R", MAX9880A_RIGHT_VOLUME_CTRL },
{ "LIOULVL L", MAX9880A_LEFT_LINE_OUTPUT_LEVEL },
{ "LIOULVL R", MAX9880A_RIGHT_LINE_OUTPUT_LEVEL },
{ "MICGAIN L", MAX9880A_LEFT_MIC_GAIN },
{ "MICGAIN R", MAX9880A_RIGHT_MIC_GAIN },
// Configuration
{ "INPUT ", MAX9880A_INPUT },
{ "MIC ", MAX9880A_MICROPHONE },
{ "MODE ", MAX9880A_MODE },
{ "JACK DET ", MAX9880A_JACK_DETECT },
// Power Management
{ "ENABLE ", MAX9880A_ENABLE },
{ "SHUTDOWN ", MAX9880A_SYSTEM_SHUTDOWN },
{ "REV ID ", MAX9880A_REVISION_ID },
};
#define MAX9880A_REG_LENGTH (sizeof(max9880a_reg_table) / sizeof(max9880a_reg_table[0]))
uint32_t max9880a_dump_reg(MAX9880A_DEF_PTR obj)
{
int32_t ercd;
uint8_t buffer_rx[MAX9880A_REG_LENGTH - 1];// ignore last register (rev id)
DEV_IIC_PTR iic_obj = iic_get_dev(obj->i2c_id);
MAX9880A_CHECK_EXP(iic_obj != NULL, E_OBJ);
ercd = iic_obj->iic_read((void *)buffer_rx, MAX9880A_REG_LENGTH - 1);
for (int i = 0; i < MAX9880A_REG_LENGTH - 1; i++) {
dbg_printf(DBG_LESS_INFO, " %s (0x%x) = 0x%x\n\r", max9880a_reg_table[i].str, max9880a_reg_table[i].reg, buffer_rx[i]);
}
error_exit:
return ercd;
}
uint32_t max9880a_config(MAX9880A_DEF_PTR obj, max9880a_config_t config)
{
int32_t ercd;
max9880a_settings_t *ptr;
uint32_t length;
uint8_t value[2];
DEV_IIC_PTR iic_obj = iic_get_dev(obj->i2c_id);
MAX9880A_CHECK_EXP(iic_obj != NULL, E_OBJ);
switch (config) {
case MAX9880A_I2SIN_LINEOUT_13MHZ:
ptr = (max9880a_settings_t *)settings_i2sin_lineout_13mhz;
length = SETTINGS_I2SIN_LINEOUT_13MHZ_LENGTH;
break;
break;
case MAX9880A_LINEIN_I2SOUT_13MHZ:
ptr = (max9880a_settings_t *)settings_linein_i2sout_13mhz;
length = SETTINGS_LINEIN_I2SOUT_13MHZ_LENGTH;
break;
break;
case MAX9880A_I2SIN_LINEOUT_12DOT288MHZ:
ptr = (max9880a_settings_t *)settings_i2sin_lineout_12_288mhz;
length = SETTINGS_I2SIN_LINEOUT_12_288MHZ_LENGTH;
break;
break;
case MAX9880A_LINEIN_I2SOUT_12DOT288MHZ:
ptr = (max9880a_settings_t *)settings_linein_i2sout_12_288mhz;
length = SETTINGS_LINEIN_I2SOUT_12_288MHZ_LENGTH;
break;
break;
case MAX9880A_I2SIN_LINEOUT_24DOT567MHZ:
ptr = (max9880a_settings_t *)settings_i2sin_lineout_24_567mhz;
length = SETTINGS_I2SIN_LINEOUT_24_567MHZ_LENGTH;
break;
break;
case MAX9880A_LINEIN_I2SOUT_24DOT567MHZ:
ptr = (max9880a_settings_t *)settings_linein_i2sout_24_567mhz;
length = SETTINGS_LINEIN_I2SOUT_24_567MHZ_LENGTH;
break;
break;
case MAX9880A_DAI2_I2SIN_LINEOUT_24DOT567MHZ:
ptr = (max9880a_settings_t *)settings_dai2_i2sin_lineout_24_567mhz;
length = SETTINGS_DAI2_I2SIN_LINEOUT_24_567MHZ_LENGTH;
break;
break;
case MAX9880A_LINEIN_DAI1_I2SOUT_24DOT567MHZ:
ptr = (max9880a_settings_t *)settings_linein_dai1_i2sout_24_567mhz;
length = SETTINGS_LINEIN_DAI1_I2SOUT_24_567MHZ_LENGTH;
break;
break;
case MAX9880A_24DOT567MHZ:
ptr = (max9880a_settings_t *)settings_24_567mhz;
length = SETTINGS_24_567MHZ_LENGTH;
break;
default:
ptr = NULL;
length = 0;
break;
}
for (int i = 0; i < length; i++) {
value[0] = (uint8_t)(ptr[i].reg);
value[1] = (uint8_t)(ptr[i].val);
ercd = iic_obj->iic_write(value, 2);
dbg_printf(DBG_MORE_INFO, "[%d]iic_write 0x%x 0x%x ret %d\r\n", i, value[0], value[1], ercd);
MAX9880A_CHECK_EXP(ercd == 2, E_SYS);
}
ercd = E_OK;
error_exit:
return ercd;
}
uint32_t max9880a_init(MAX9880A_DEF_PTR obj)
{
int32_t ercd;
DEV_IIC_PTR iic_obj = iic_get_dev(obj->i2c_id);
MAX9880A_CHECK_EXP(iic_obj != NULL, E_OBJ);
ercd = iic_obj->iic_open(DEV_MASTER_MODE, IIC_SPEED_STANDARD);
dbg_printf(DBG_MORE_INFO, "[%s]iic_open ret %d\r\n", __FUNCTION__, ercd);// should return E_OK
MAX9880A_CHECK_EXP(ercd == E_OK, E_SYS);
ercd = iic_obj->iic_control(IIC_CMD_ENA_DEV, (void *)obj->slvaddr);
dbg_printf(DBG_MORE_INFO, "[%s]iic_control IIC_CMD_ENA_DEV ret %d\r\n", __FUNCTION__, ercd);// should return E_OK
MAX9880A_CHECK_EXP(ercd == E_OK, E_SYS);
ercd = iic_obj->iic_control(IIC_CMD_SET_ADDR_MODE, IIC_7BIT_ADDRESS);
dbg_printf(DBG_MORE_INFO, "[%s]iic_control IIC_CMD_SET_ADDR_MODE ret %d\r\n", __FUNCTION__, ercd);// should return E_OK
MAX9880A_CHECK_EXP(ercd == E_OK, E_SYS);
ercd = iic_obj->iic_control(IIC_CMD_MST_SET_TAR_ADDR, (void *)obj->slvaddr);
dbg_printf(DBG_MORE_INFO, "[%s]iic_control IIC_CMD_MST_SET_TAR_ADDR ret %d\r\n", __FUNCTION__, ercd);// should return E_OK
MAX9880A_CHECK_EXP(ercd == E_OK, E_SYS);
// dbg_printf(DBG_LESS_INFO, "max9880a_init\n\r");
error_exit:
return ercd;
}
uint32_t max9880a_deinit(MAX9880A_DEF_PTR obj)
{
int32_t ercd;
DEV_IIC_PTR iic_obj = iic_get_dev(obj->i2c_id);
MAX9880A_CHECK_EXP(iic_obj != NULL, E_OBJ);
ercd = iic_obj->iic_close();
error_exit:
return ercd;
}

View File

@@ -1,94 +0,0 @@
/* ------------------------------------------
* Copyright (c) 2018, Synopsys, Inc. All rights reserved.
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
* 1) Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2) Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
* 3) Neither the name of the Synopsys, Inc., nor the names of its contributors may
* be used to endorse or promote products derived from this software without
* specific prior written permission.
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
--------------------------------------------- */
#ifndef H_MAX9880A
#define H_MAX9880A
// MAX9800A (Low-Power, High-Performance, Dual I²S, Stereo Audio Codec) is on EMSDP board
#define I2C_DEVICE_ADDRESS_MAX9880A (0x10)
typedef enum {
/**
* Use external MCLK of 13 MHz
* S1 pins are mapped on DAI1
* S2 pins are mapped on DAI2
*/
MAX9880A_I2SIN_LINEOUT_13MHZ = 0, // Playback
MAX9880A_LINEIN_I2SOUT_13MHZ, // Recording
/**
* Use no external MCLK, but route Xtal to clk-prescaler
* S1 pins are mapped on DAI1
* S2 pins are mapped on DAI2
*/
MAX9880A_I2SIN_LINEOUT_12DOT288MHZ, // Playback
MAX9880A_LINEIN_I2SOUT_24DOT567MHZ, // Recording
/**
* Use external MCLK of 24.567 MHz
* S1 pins are mapped on DAI1
* S2 pins are mapped on DAI2
*/
MAX9880A_I2SIN_LINEOUT_24DOT567MHZ, // Playback
MAX9880A_LINEIN_I2SOUT_24DOT567MHZ, // Recording
/**
* !!!! Use these settings for HSDK-IC on BOARD !!!!
*
* Mapping is now different
* S1 pins are mapped on DAI2
* S2 pins are mapped on DAI1
*
* Use external MCLK of 24.567 MHz
* Use DAI2 (S1) for playback (I2S-TX), Use DAI1 (S2) for recording (I2S-RX)
*/
MAX9880A_DAI2_I2SIN_LINEOUT_24DOT567MHZ, // Playback
MAX9880A_LINEIN_DAI1_I2SOUT_24DOT567MHZ, // Recording
MAX9880A_24DOT567MHZ, // PlayBack and Recording (Regression)
} max9880a_config_t;
/* temperature sensor object type*/
typedef struct {
uint32_t i2c_id;
uint32_t slvaddr;
} MAX9880A_DEF, *MAX9880A_DEF_PTR;
#define MAX9880A_DEFINE(NAME, I2C_ID, SLAVE_ADDRESS) \
MAX9880A_DEF __ ## NAME = { \
.i2c_id = I2C_ID, \
.slvaddr = SLAVE_ADDRESS, \
}; \
MAX9880A_DEF_PTR NAME = &__ ## NAME
extern uint32_t max9880a_dump_reg(MAX9880A_DEF_PTR obj);
extern uint32_t max9880a_config(MAX9880A_DEF_PTR obj, max9880a_config_t config);
extern uint32_t max9880a_init(MAX9880A_DEF_PTR obj);
extern uint32_t max9880a_deinit(MAX9880A_DEF_PTR obj);
#endif /* H_MAX9880A */

View File

@@ -1,2 +0,0 @@
DEV_CSRCDIR += $(EMBARC_ROOT)/device/peripheral/audio/max9880a
DEV_INCDIR += $(EMBARC_ROOT)/device/peripheral/audio/max9880a

View File

@@ -1,2 +0,0 @@
DEV_CSRCDIR += $(EMBARC_ROOT)/device/peripheral/flash/fl256s
DEV_INCDIR += $(EMBARC_ROOT)/device/peripheral/flash/fl256s

View File

@@ -1,507 +0,0 @@
/* ------------------------------------------
* Copyright (c) 2018, 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.
*
--------------------------------------------- */
#include "embARC.h"
#include "spi_flash_fl256s.h"
// #define DBG_MORE
#include "embARC_debug.h"
#define RDID 0x9F /*!<read chip ID */
#define RDSR1 0x05 /*!< read status register-1 */
#define WRSR1 0x01 /*!< write status registe-1 */
#define RDSR2 0x07 /*!< read status register-2 */
#define RDCR 0x35 /*!< read config register */
#define WREN 0x06 /*!< write enablewaitDeviceReady */
#define WRDI 0x04 /*!< write disable */
#define READ 0x03 /*!< read data bytes */
#define QORD 0x6B
#define SE 0x20 /*!< sector erase */
#define PP 0x02 /*!< page program */
#define QPP 0x32 /*!< page program */
#define FL256S_NOT_VALID (0xFFFFFFFF)
/**
* @fn int32_t _spi_send_cmd(FL256S_DEF_PTR dev, DEV_SPI_TRANSFER *xfer)
*/
Inline int32_t _spi_send_cmd(FL256S_DEF_PTR dev, DEV_SPI_TRANSFER *xfer)
{
uint32_t cpu_status;
DEV_SPI_PTR spi_flash;
int32_t ercd = 0;
spi_flash = spi_get_dev(dev->spi_master);
// cpu_status = cpu_lock_save();
/* select device */
spi_flash->spi_control(SPI_CMD_MST_SEL_DEV, CONV2VOID((uint32_t)dev->cs));
spi_flash->spi_control(SPI_CMD_MST_SET_FREQ, CONV2VOID(dev->spi_freq));
spi_flash->spi_control(SPI_CMD_SET_CLK_MODE, CONV2VOID(SPI_CLK_MODE_0));
ercd = spi_flash->spi_control(SPI_CMD_TRANSFER_POLLING, CONV2VOID(xfer));
/* deselect device */
spi_flash->spi_control(SPI_CMD_MST_DSEL_DEV, CONV2VOID((uint32_t)dev->cs));
// cpu_unlock_restore(cpu_status);
return ercd;
}
/**
* @fn int32_t _spi_send_cmd_quad(FL256S_DEF_PTR dev, DEV_SPI_PAK_PTR pak_ptr)
*/
Inline int32_t _spi_send_cmd_quad(FL256S_DEF_PTR dev, DEV_SPI_PAK_PTR pak_ptr)
{
uint32_t cpu_status;
DEV_SPI_PTR spi_flash;
int32_t ercd = 0;
spi_flash = spi_get_dev(dev->spi_master);
// cpu_status = cpu_lock_save();
/* select device */
spi_flash->spi_control(SPI_CMD_MST_SEL_DEV, CONV2VOID((uint32_t)dev->cs));
spi_flash->spi_control(SPI_CMD_MST_SET_FREQ, CONV2VOID(dev->spi_freq));
spi_flash->spi_control(SPI_CMD_SET_CLK_MODE, CONV2VOID(SPI_CLK_MODE_0));
ercd = spi_flash->spi_control(SPI_CMD_QUAD_READ, CONV2VOID(pak_ptr));
/* deselect device */
spi_flash->spi_control(SPI_CMD_MST_DSEL_DEV, CONV2VOID((uint32_t)dev->cs));
// cpu_unlock_restore(cpu_status);
return ercd;
}
uint32_t fl256s_read_reg(FL256S_DEF_PTR dev, uint8_t reg, uint8_t *data, uint32_t len)
{
DEV_SPI_TRANSFER cmd_xfer = { 0 };
DEV_SPI_TRANSFER data_xfer = { 0 };
DEV_SPI_XFER_SET_TXBUF(&data_xfer, NULL, 0, 0);
DEV_SPI_XFER_SET_RXBUF(&data_xfer, data, 0, len);
DEV_SPI_XFER_SET_NEXT(&data_xfer, NULL);
DEV_SPI_XFER_SET_TXBUF(&cmd_xfer, &reg, 0, 1);
DEV_SPI_XFER_SET_RXBUF(&cmd_xfer, NULL, 0, 0);
DEV_SPI_XFER_SET_NEXT(&cmd_xfer, &data_xfer);
if (_spi_send_cmd(dev, &cmd_xfer) == 0) {
return len;
} else {
return FL256S_NOT_VALID;
}
}
uint32_t fl256s_write_reg(FL256S_DEF_PTR dev, uint8_t reg, uint8_t *data, uint32_t len)
{
DEV_SPI_TRANSFER cmd_xfer = { 0 };
DEV_SPI_TRANSFER data_xfer = { 0 };
DEV_SPI_XFER_SET_TXBUF(&data_xfer, data, 0, len);
DEV_SPI_XFER_SET_RXBUF(&data_xfer, NULL, 0, 0);
DEV_SPI_XFER_SET_NEXT(&data_xfer, NULL);
DEV_SPI_XFER_SET_TXBUF(&cmd_xfer, &reg, 0, 1);
DEV_SPI_XFER_SET_RXBUF(&cmd_xfer, NULL, 0, 0);
DEV_SPI_XFER_SET_NEXT(&cmd_xfer, &data_xfer);
if (_spi_send_cmd(dev, &cmd_xfer) == 0) {
return len;
} else {
return FL256S_NOT_VALID;
}
}
int32_t fl256s_quad_enable(FL256S_DEF_PTR dev)
{
uint32_t status = 0;
uint8_t w_data[2] = { 0 };
uint8_t r_data = 0;
status = fl256s_read_reg(dev, RDCR, &r_data, 1);
if (status == FL256S_NOT_VALID) {
return -1;
}
if (!(r_data & 0x02)) {
w_data[1] = r_data | 0x02;
status = fl256s_read_reg(dev, RDSR1, &r_data, 1);
if (status == FL256S_NOT_VALID) {
return -1;
}
w_data[0] = r_data;
if (fl256s_write_enable(dev) != 0) {
return -1;
}
status = fl256s_write_reg(dev, WRSR1, w_data, 2);
if (status == FL256S_NOT_VALID) {
return -1;
}
dev->quad_en = 1;
} else {
dev->quad_en = 1;
}
return 0;
}
int32_t fl256s_quad_disable(FL256S_DEF_PTR dev)
{
uint32_t status = 0;
uint8_t w_data[2] = { 0 };
uint8_t r_data = 0;
status = fl256s_read_reg(dev, RDCR, &r_data, 1);
if (status == FL256S_NOT_VALID) {
return -1;
}
if (r_data & 0x02) {
w_data[1] = r_data & 0xFD;
status = fl256s_read_reg(dev, RDSR1, &r_data, 1);
if (status == FL256S_NOT_VALID) {
return -1;
}
w_data[0] = r_data;
if (fl256s_write_enable(dev) != 0) {
return -1;
}
status = fl256s_write_reg(dev, WRSR1, w_data, 2);
if (status == FL256S_NOT_VALID) {
return -1;
}
dev->quad_en = 0;
} else {
dev->quad_en = 0;
}
return 0;
}
uint32_t fl256s_read_id(FL256S_DEF_PTR dev)
{
uint32_t id = 0;
uint8_t local_buf[5];
DEV_SPI_TRANSFER cmd_xfer;
local_buf[0] = RDID;
DEV_SPI_XFER_SET_TXBUF(&cmd_xfer, local_buf, 0, 1);
DEV_SPI_XFER_SET_RXBUF(&cmd_xfer, local_buf, 0, 5);
DEV_SPI_XFER_SET_NEXT(&cmd_xfer, NULL);
if (_spi_send_cmd(dev, &cmd_xfer) == 0) {
id = (local_buf[1] << 24) | (local_buf[2] << 16) | (local_buf[3] << 8) | local_buf[4];
} else {
id = FL256S_NOT_VALID;
}
dbg_printf(DBG_MORE_INFO, "fl256s_read_id buf: 0x%x, 0x%x, 0x%x, 0x%x, 0x%x\r\n", local_buf[0], local_buf[1], local_buf[2], local_buf[3], local_buf[4]);
return id;
}
int32_t fl256s_wait_ready(FL256S_DEF_PTR dev)
{
uint32_t status = 0x01;
uint8_t r_data = 0;
do {
status = fl256s_read_reg(dev, RDSR1, &r_data, 1);
if (status == FL256S_NOT_VALID) {
return -1;
}
} while (r_data & 0x01);// Status Register 1 Bit 0
return 0;
}
int32_t fl256s_init(FL256S_DEF_PTR dev, uint32_t freq)
{
DEV_SPI_PTR spi_flash;
int32_t ercd = 0;
dev->spi_freq = freq;
spi_flash = spi_get_dev(dev->spi_master);
ercd = spi_flash->spi_open(DEV_MASTER_MODE, freq);
if (ercd != E_OK && ercd != E_OPNED) {
return ercd;
}
// spi_flash->spi_control(SPI_CMD_SET_DUMMY_DATA, CONV2VOID(0xFF));
ercd = fl256s_wait_ready(dev);
dbg_printf(DBG_MORE_INFO, "fl256s_wait_ready ret %d\r\n", ercd);
return E_OK;
}
int32_t fl256s_write_enable(FL256S_DEF_PTR dev)
{
uint32_t status = 0;
uint8_t w_data, r_data = 0;
do {
status = fl256s_write_reg(dev, WREN, &w_data, 0);
if (status == FL256S_NOT_VALID) {
return -1;
}
status = fl256s_read_reg(dev, RDSR1, &r_data, 1);
if (status == FL256S_NOT_VALID) {
return -1;
}
// clear protection bits
// Write Protect. and Write Enable.
if ((r_data & 0xfc) && (r_data & 0x02)) {
w_data = 0;
status = fl256s_write_reg(dev, WRSR1, &w_data, 1);
if (status == FL256S_NOT_VALID) {
return -1;
}
r_data = 0;
}
} while (r_data != 0x02);
return 0;
}
int32_t fl256s_write_disable(FL256S_DEF_PTR dev)
{
uint32_t status = 0;
uint8_t w_data, r_data = 0;
do {
status = fl256s_write_reg(dev, WRDI, &w_data, 0);
if (status == FL256S_NOT_VALID) {
return -1;
}
status = fl256s_read_reg(dev, RDSR1, &r_data, 1);
if (status == FL256S_NOT_VALID) {
return -1;
}
dbg_printf(DBG_MORE_INFO, "fl256s_write_disable status = 0x%x\r\n", r_data);
if (status == FL256S_NOT_VALID) {
return -1;
}
} while (r_data & 0x02);// Status Register 1 Bit 1
return 0;
}
int32_t fl256s_erase(FL256S_DEF_PTR dev, uint32_t address, uint32_t size)
{
uint32_t last_address;
uint32_t count = 0;
uint8_t local_buf[4];
DEV_SPI_TRANSFER cmd_xfer;
// start address of last sector
last_address = (address + size) & (~(dev->sector_sz - 1));
// start address of first sector
address &= ~(dev->sector_sz - 1);
do {
if (fl256s_write_enable(dev) != 0) {
return -1;
}
if (fl256s_wait_ready(dev) != 0) {
return -1;
}
local_buf[0] = SE;
local_buf[1] = (address >> 16) & 0xff;
local_buf[2] = (address >> 8) & 0xff;
local_buf[3] = address & 0xff;
DEV_SPI_XFER_SET_TXBUF(&cmd_xfer, local_buf, 0, 4);
DEV_SPI_XFER_SET_RXBUF(&cmd_xfer, NULL, 0, 0);
DEV_SPI_XFER_SET_NEXT(&cmd_xfer, NULL);
if (_spi_send_cmd(dev, &cmd_xfer) != 0) {
return -1;
}
address += dev->sector_sz;
count++;
} while (address <= last_address);
if (fl256s_wait_ready(dev) != 0) {
return -1;
}
if (fl256s_write_disable(dev) != 0) {
return -1;
}
return (int32_t)count;
}
int32_t fl256s_write(FL256S_DEF_PTR dev, uint32_t address, uint32_t size, const void *data)
{
uint8_t local_buf[4];
DEV_SPI_TRANSFER cmd_xfer;
DEV_SPI_TRANSFER data_xfer;
uint32_t first = 0;
uint32_t size_orig = size;
if (fl256s_wait_ready(dev) != 0) {
return -1;
}
first = FLASH_PAGE_SIZE - (address & (FLASH_PAGE_SIZE - 1));
do {
// send write enable command to flash
if (fl256s_write_enable(dev) != 0) {
return -1;
}
if (fl256s_wait_ready(dev) != 0) {
return -1;
}
first = first < size ? first : size;
local_buf[0] = PP;
local_buf[1] = (address >> 16) & 0xff;
local_buf[2] = (address >> 8) & 0xff;
local_buf[3] = address & 0xff;
DEV_SPI_XFER_SET_TXBUF(&data_xfer, data, 0, first);
DEV_SPI_XFER_SET_RXBUF(&data_xfer, NULL, 0, 0);
DEV_SPI_XFER_SET_NEXT(&data_xfer, NULL);
DEV_SPI_XFER_SET_TXBUF(&cmd_xfer, local_buf, 0, 4);
DEV_SPI_XFER_SET_RXBUF(&cmd_xfer, NULL, 0, 0);
DEV_SPI_XFER_SET_NEXT(&cmd_xfer, &data_xfer);
if (_spi_send_cmd(dev, &cmd_xfer) != 0) {
return -1;
}
size -= first;
address += first;
data += first;
first = FLASH_PAGE_SIZE;
} while (size);
if (fl256s_wait_ready(dev) != 0) {
return -1;
}
if (fl256s_write_disable(dev) != 0) {
return -1;
}
return (int32_t)(size_orig);
}
int32_t fl256s_read(FL256S_DEF_PTR dev, uint32_t address, uint32_t size, void *data)
{
uint8_t local_buf[4];
DEV_SPI_TRANSFER cmd_xfer;
DEV_SPI_TRANSFER data_xfer;
uint32_t first = 0;
uint32_t size_orig = size;
first = FLASH_PAGE_SIZE - (address & (FLASH_PAGE_SIZE - 1));
do {
if (fl256s_wait_ready(dev) != 0) {
return -1;
}
first = first < size ? first : size;
local_buf[0] = READ;
local_buf[1] = (address >> 16) & 0xff;
local_buf[2] = (address >> 8) & 0xff;
local_buf[3] = address & 0xff;
DEV_SPI_XFER_SET_TXBUF(&data_xfer, NULL, 0, 0);
DEV_SPI_XFER_SET_RXBUF(&data_xfer, data, 0, first);
DEV_SPI_XFER_SET_NEXT(&data_xfer, NULL);
DEV_SPI_XFER_SET_TXBUF(&cmd_xfer, local_buf, 0, 4);
DEV_SPI_XFER_SET_RXBUF(&cmd_xfer, NULL, 0, 0);
DEV_SPI_XFER_SET_NEXT(&cmd_xfer, &data_xfer);
if (_spi_send_cmd(dev, &cmd_xfer) != 0) {
return -1;
}
size -= first;
address += first;
data += first;
first = FLASH_PAGE_SIZE;
} while (size);
return (int32_t)(size_orig);
}
int32_t fl256s_quad_read(FL256S_DEF_PTR dev, uint32_t address, uint32_t size, void *data)
{
DEV_SPI_PAK spi_pak;
uint32_t first = 0;
uint32_t size_orig = size;
uint32_t per_read_size = 32;
first = per_read_size - (address & (per_read_size - 1));
do {
if (fl256s_wait_ready(dev) != 0) {
return -1;
}
first = first < size ? first : size;
spi_pak.cmd = QORD;
spi_pak.addr32 = address;
spi_pak.data_len = first;
spi_pak.data_ptr = data;
if (_spi_send_cmd_quad(dev, &spi_pak) != 0) {
return -1;
}
size -= first;
address += first;
data += first;
first = per_read_size;
} while (size);
return (int32_t)(size_orig);
}

View File

@@ -1,93 +0,0 @@
/* ------------------------------------------
* Copyright (c) 2018, Synopsys, Inc. All rights reserved.
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
* 1) Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2) Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
* 3) Neither the name of the Synopsys, Inc., nor the names of its contributors may
* be used to endorse or promote products derived from this software without
* specific prior written permission.
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
--------------------------------------------- */
#ifndef H_SPI_FLASH_FL256S
#define H_SPI_FLASH_FL256S
// Manufacturer: 0x01, DeviceId: 0x0219, ID-CFI: 0x4D
#define FLASH_ID 0x0102194D
#define FLASH_SECTOR_SIZE 0x00001000
#define FLASH_PAGE_SIZE 0x00000100
#include "embARC_toolchain.h"
#include "embARC_error.h"
/** flash data type */
typedef struct {
uint32_t head; /*!< 0x68656164 ='head' */
uint32_t cpu_type; /*!< = 0 - all images, reserved for future */
uint32_t start; /*!< start address of application image in spi flash */
uint32_t size; /*!< size of image in bytes */
uint32_t ramaddr; /*!< address of ram for loading image */
uint32_t ramstart; /*!< start address of application in RAM !!!! */
uint32_t checksum; /*!< checksum of all bytes in image */
} image_t;
/** fl256s object type */
typedef struct {
uint8_t spi_master;
uint8_t cs;
uint8_t quad_en;
uint32_t spi_freq;
uint32_t page_sz;
uint32_t sector_sz;
} FL256S_DEF, *FL256S_DEF_PTR;
#define FL256S_DEF(name, spi_master_id, cs_line, page, sector) \
FL256S_DEF __ ## name = { \
.spi_master = spi_master_id, \
.cs = cs_line, \
.page_sz = page, \
.sector_sz = sector \
}; \
FL256S_DEF_PTR name = &__ ## name \
#ifdef __cplusplus
extern "C" {
#endif
extern uint32_t fl256s_read_status(FL256S_DEF_PTR dev);
extern uint32_t fl256s_read_id(FL256S_DEF_PTR dev);
extern int32_t fl256s_read(FL256S_DEF_PTR dev, uint32_t address, uint32_t size, void *data);
extern int32_t fl256s_quad_read(FL256S_DEF_PTR dev, uint32_t address, uint32_t size, void *data);
extern int32_t fl256s_write_enable(FL256S_DEF_PTR dev);
extern int32_t fl256s_write_disable(FL256S_DEF_PTR dev);
extern int32_t fl256s_erase(FL256S_DEF_PTR dev, uint32_t address, uint32_t size);
extern int32_t fl256s_write(FL256S_DEF_PTR dev, uint32_t address, uint32_t size, const void *data);
extern int32_t fl256s_wait_ready(FL256S_DEF_PTR dev);
extern int32_t fl256s_init(FL256S_DEF_PTR dev, uint32_t freq);
extern int32_t fl256s_quad_enable(FL256S_DEF_PTR dev);
extern int32_t fl256s_quad_disable(FL256S_DEF_PTR dev);
#ifdef __cplusplus
}
#endif
#endif /* H_SPI_FLASH_FL256S */

View File

@@ -1,371 +0,0 @@
/* ------------------------------------------
* 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.
*
--------------------------------------------- */
#include "spi_flash_w25qxx.h"
#include "embARC_error.h"
#include "board.h"
#include "device/ip_hal/dev_spi.h"
#include "arc/arc_exception.h"
#include "string.h"
/**
* @name W25QXX SPI Flash Commands
* @{
*/
#define RDID 0x9F /*!<read chip ID */
#define RDSR 0x05 /*!< read status register */
#define WRSR 0x01 /*!< write status register */
#define WREN 0x06 /*!< write enablewaitDeviceReady */
#define WRDI 0x04 /*!< write disable */
#define READ 0x03 /*!< read data bytes */
#define SE 0x20 /*!< sector erase */
#define PP 0x02 /*!< page program */
/** @} end of name */
#define W25QXX_NOT_VALID (0xFFFFFFFF)
/**
* @fn int32_t spi_send_cmd(W25QXX_DEF_PTR dev, DEV_SPI_TRANSFER *xfer)
* @brief SPI flash spi send command to operate spi flash
* @param[in] xfer SPI transfer that need to transfer to spi device
* @retval 0 success
* @retval -1 fail
*/
Inline int32_t spi_send_cmd(W25QXX_DEF_PTR dev, DEV_SPI_TRANSFER *xfer)
{
DEV_SPI_PTR spi_flash;
int32_t ercd = 0;
spi_flash = spi_get_dev(dev->spi_master);
/* select device */
spi_flash->spi_control(SPI_CMD_MST_SEL_DEV, CONV2VOID((uint32_t)dev->cs));
spi_flash->spi_control(SPI_CMD_MST_SET_FREQ, CONV2VOID(dev->spi_freq));
spi_flash->spi_control(SPI_CMD_SET_CLK_MODE, CONV2VOID(SPI_CLK_MODE_0));
ercd = spi_flash->spi_control(SPI_CMD_TRANSFER_POLLING, CONV2VOID(xfer));
/* deselect device */
spi_flash->spi_control(SPI_CMD_MST_DSEL_DEV, CONV2VOID((uint32_t)dev->cs));
return ercd;
}
/**
* @brief Read the status of spi flash
* @return Current status of spi flash
*/
uint32_t w25qxx_read_status(W25QXX_DEF_PTR dev)
{
uint8_t local_buf[2];
DEV_SPI_TRANSFER cmd_xfer;
local_buf[0] = RDSR;
DEV_SPI_XFER_SET_TXBUF(&cmd_xfer, local_buf, 0, 1);
DEV_SPI_XFER_SET_RXBUF(&cmd_xfer, local_buf, 1, 1);
DEV_SPI_XFER_SET_NEXT(&cmd_xfer, NULL);
if (spi_send_cmd(dev, &cmd_xfer) == 0) {
return (uint32_t)local_buf[0];
} else {
return W25QXX_NOT_VALID;
}
}
/**
* @brief Enable to write flash
* @retval 0 Enable operation successfully
* @retval -1 Enable operation failed
*/
int32_t w25qxx_write_enable(W25QXX_DEF_PTR dev)
{
uint8_t local_buf[3];
DEV_SPI_TRANSFER cmd_xfer;
uint32_t status = 0;
do {
local_buf[0] = WREN;
DEV_SPI_XFER_SET_TXBUF(&cmd_xfer, local_buf, 0, 1);
DEV_SPI_XFER_SET_RXBUF(&cmd_xfer, NULL, 0, 0);
DEV_SPI_XFER_SET_NEXT(&cmd_xfer, NULL);
if (spi_send_cmd(dev, &cmd_xfer) != 0) {
return -1;
}
status = w25qxx_read_status(dev);
if (status == W25QXX_NOT_VALID) {
return -1;
}
// clear protection bits
// Write Protect. and Write Enable.
if ((status & 0xfc) && (status & 0x02)) {
local_buf[0] = WRSR; // write status
local_buf[1] = 0x00; // write status
local_buf[2] = 0x00; // write status
DEV_SPI_XFER_SET_TXBUF(&cmd_xfer, local_buf, 0, 3);
DEV_SPI_XFER_SET_RXBUF(&cmd_xfer, NULL, 0, 0);
DEV_SPI_XFER_SET_NEXT(&cmd_xfer, NULL);
if (spi_send_cmd(dev, &cmd_xfer) != 0) {
return -1;
}
status = 0;
}
} while (status != 0x02);
return 0;
}
/**
* @brief Initialize spi flash interface
* @retval 0 Initialize successfully
* @retval -1 Initialize failed
*/
int32_t w25qxx_init(W25QXX_DEF_PTR dev, uint32_t freq)
{
DEV_SPI_PTR spi_flash;
int32_t ercd = 0;
dev->spi_freq = freq;
spi_flash = spi_get_dev(dev->spi_master);
ercd = spi_flash->spi_open(DEV_MASTER_MODE, freq);
if (ercd != E_OK && ercd != E_OPNED) {
return ercd;
}
spi_flash->spi_control(SPI_CMD_SET_DUMMY_DATA, CONV2VOID(0xFF));
return E_OK;
}
/**
* @brief Read spi flash identification ID
* @return The id of the spi flash
*/
uint32_t w25qxx_read_id(W25QXX_DEF_PTR dev)
{
uint32_t id = 0;
uint8_t local_buf[4];
DEV_SPI_TRANSFER cmd_xfer;
local_buf[0] = RDID;
DEV_SPI_XFER_SET_TXBUF(&cmd_xfer, local_buf, 0, 1);
DEV_SPI_XFER_SET_RXBUF(&cmd_xfer, local_buf, 1, 3);
DEV_SPI_XFER_SET_NEXT(&cmd_xfer, NULL);
if (spi_send_cmd(dev, &cmd_xfer) == 0) {
id = (local_buf[0] << 16) | (local_buf[1] << 8) | local_buf[2];
} else {
id = W25QXX_NOT_VALID;
}
return id;
}
/**
* @brief Read status and wait while busy flag is set
* @retval 0 Success
* @retval -1 Fail
*/
int32_t w25qxx_wait_ready(W25QXX_DEF_PTR dev)
{
uint32_t status = 0x01;
do {
status = w25qxx_read_status(dev);
if (status == W25QXX_NOT_VALID) {
return -1;
}
} while (status & 0x01);
return 0;
}
/**
* @brief Read data from flash
* @param[in] address Start address
* @param[in] size Data size
* @param[out] data Pointer to the return data
*
* @retval -1 Read failed
* @retval >= 0 Data size
*/
int32_t w25qxx_read(W25QXX_DEF_PTR dev, uint32_t address, uint32_t size, void *data)
{
uint8_t local_buf[4];
DEV_SPI_TRANSFER cmd_xfer;
local_buf[0] = READ;
local_buf[1] = (address >> 16) & 0xff;
local_buf[2] = (address >> 8) & 0xff;
local_buf[3] = address & 0xff;
DEV_SPI_XFER_SET_TXBUF(&cmd_xfer, local_buf, 0, 4);
DEV_SPI_XFER_SET_RXBUF(&cmd_xfer, data, 4, size);
DEV_SPI_XFER_SET_NEXT(&cmd_xfer, NULL);
if (spi_send_cmd(dev, &cmd_xfer) == 0) {
return size;
} else {
return -1;
}
}
/**
* @brief Flash erase in sectors
*
* @param[in] address Erase start address of spi flash
* @param[in] size Erase size
*
* @retval -1 Erase failed
* @retval >= 0 Sector count erased
*/
int32_t w25qxx_erase(W25QXX_DEF_PTR dev, uint32_t address, uint32_t size)
{
uint32_t last_address;
uint32_t count = 0;
uint8_t local_buf[4];
DEV_SPI_TRANSFER cmd_xfer;
// start address of last sector
last_address = (address + size) & (~(dev->sector_sz - 1));
// start address of first sector
address &= ~(dev->sector_sz - 1);
do {
if (w25qxx_write_enable(dev) != 0) {
return -1;
}
if (w25qxx_wait_ready(dev) != 0) {
return -1;
}
local_buf[0] = SE;
local_buf[1] = (address >> 16) & 0xff;
local_buf[2] = (address >> 8) & 0xff;
local_buf[3] = address & 0xff;
DEV_SPI_XFER_SET_TXBUF(&cmd_xfer, local_buf, 0, 4);
DEV_SPI_XFER_SET_RXBUF(&cmd_xfer, NULL, 0, 0);
DEV_SPI_XFER_SET_NEXT(&cmd_xfer, NULL);
if (spi_send_cmd(dev, &cmd_xfer) != 0) {
return -1;
}
address += dev->sector_sz;
count++;
} while (address <= last_address);
if (w25qxx_wait_ready(dev) != 0) {
return -1;
}
return (int32_t)count;
}
/**
* @brief Write data to spi flash
*
* @param[in] address Start address
* @param[in] size Data size
* @param[in] data Pointer to data
*
* @retval >= 0 Written bytes number
* @retval < 0 Write data failed
*/
int32_t w25qxx_write(W25QXX_DEF_PTR dev, uint32_t address, uint32_t size, const void *data)
{
DEV_SPI_TRANSFER cmd_xfer;
uint32_t first = 0;
uint32_t size_orig = size;
if (w25qxx_wait_ready(dev) != 0) {
return -1;
}
first = FLASH_PAGE_SIZE - (address & (FLASH_PAGE_SIZE - 1));
do {
// send write enable command to flash
if (w25qxx_write_enable(dev) != 0) {
return -1;
}
if (w25qxx_wait_ready(dev) != 0) {
return -1;
}
first = first < size ? first : size;
dev->write_buf[0] = PP;
dev->write_buf[1] = (address >> 16) & 0xff;
dev->write_buf[2] = (address >> 8) & 0xff;
dev->write_buf[3] = address & 0xff;
memcpy(&(dev->write_buf[4]), data, first);
// DEV_SPI_XFER_SET_TXBUF(&data_xfer, data, 0, first);
// DEV_SPI_XFER_SET_RXBUF(&data_xfer, NULL, 0, 0);
// DEV_SPI_XFER_SET_NEXT(&data_xfer, NULL);
DEV_SPI_XFER_SET_TXBUF(&cmd_xfer, dev->write_buf, 0, 4 + first);
DEV_SPI_XFER_SET_RXBUF(&cmd_xfer, NULL, 0, 0);
DEV_SPI_XFER_SET_NEXT(&cmd_xfer, NULL);
if (spi_send_cmd(dev, &cmd_xfer) != 0) {
return -1;
}
size -= first;
address += first;
data += first;
first = FLASH_PAGE_SIZE;
} while (size);
if (w25qxx_wait_ready(dev) != 0) {
return -1;
}
return (int32_t)(size_orig);
}

View File

@@ -1,87 +0,0 @@
/* ------------------------------------------
* Copyright (c) 2017, Synopsys, Inc. All rights reserved.
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
* 1) Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2) Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
* 3) Neither the name of the Synopsys, Inc., nor the names of its contributors may
* be used to endorse or promote products derived from this software without
* specific prior written permission.
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
--------------------------------------------- */
#ifndef H_SPI_FLASH_W25QXX
#define H_SPI_FLASH_W25QXX
#define FLASH_PAGE_SIZE 0x100
#define FLASH_SECTOR_SIZE 0x1000
#include "embARC_toolchain.h"
#include "embARC_error.h"
/** flash data type */
typedef struct {
uint32_t head; /*!< 0x68656164 ='head' */
uint32_t cpu_type; /*!< = 0 - all images, reserved for future */
uint32_t start; /*!< start address of application image in spi flash */
uint32_t size; /*!< size of image in bytes */
uint32_t ramaddr; /*!< address of ram for loading image */
uint32_t ramstart; /*!< start address of application in RAM !!!! */
uint32_t checksum; /*!< checksum of all bytes in image */
} image_t;
/** w25qxx object type */
typedef struct {
uint8_t spi_master;
uint8_t cs;
uint32_t spi_freq;
uint32_t page_sz;
uint32_t sector_sz;
uint8_t write_buf[4 + FLASH_PAGE_SIZE];
} W25QXX_DEF, *W25QXX_DEF_PTR;
#define W25QXX_DEF(name, spi_master_id, cs_line, page, sector) \
W25QXX_DEF __ ## name = { \
.spi_master = spi_master_id, \
.cs = cs_line, \
.page_sz = page, \
.sector_sz = sector \
}; \
W25QXX_DEF_PTR name = &__ ## name \
#ifdef __cplusplus
extern "C" {
#endif
extern uint32_t w25qxx_read_status(W25QXX_DEF_PTR dev);
extern uint32_t w25qxx_read_id(W25QXX_DEF_PTR dev);
extern int32_t w25qxx_read(W25QXX_DEF_PTR dev, uint32_t address, uint32_t size, void *data);
extern int32_t w25qxx_write_enable(W25QXX_DEF_PTR dev);
extern int32_t w25qxx_erase(W25QXX_DEF_PTR dev, uint32_t address, uint32_t size);
extern int32_t w25qxx_write(W25QXX_DEF_PTR dev, uint32_t address, uint32_t size, const void *data);
extern int32_t w25qxx_wait_ready(W25QXX_DEF_PTR dev);
extern int32_t w25qxx_init(W25QXX_DEF_PTR dev, uint32_t freq);
#ifdef __cplusplus
}
#endif
#endif /* H_SPI_FLASH_W25QXX */

View File

@@ -1,2 +0,0 @@
DEV_CSRCDIR += $(EMBARC_ROOT)/device/peripheral/flash/w25qxx
DEV_INCDIR += $(EMBARC_ROOT)/device/peripheral/flash/w25qxx

View File

@@ -1,138 +0,0 @@
/* ------------------------------------------
* 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.
*
--------------------------------------------- */
#include <stdint.h>
#include "embARC_error.h"
#include "embARC_debug.h"
#include "board.h"
#include "cy8c95xx.h"
#define CY8C95XX_CHECK_EXP_NORTN(EXPR, ERROR_CODE) CHECK_EXP(EXPR, ercd, ERROR_CODE, error_exit)
int32_t cy8c95xx_reg_write(CY8C95XX_DEF_PTR obj, uint8_t dev, uint8_t regaddr, uint8_t *val, uint8_t len)
{
int32_t ercd = E_OK;
uint8_t data[1];
uint32_t slvaddr;
DEV_IIC_PTR iic_obj = iic_get_dev(obj->i2c_id);
dbg_printf(DBG_LESS_INFO, "[%s]%d: obj 0x%x, regaddr 0x%x, val 0x%x\r\n", __FUNCTION__, __LINE__, obj, regaddr, *val);
dbg_printf(DBG_MORE_INFO, "[%s]%d: iic_obj 0x%x -> 0x%x\r\n", __FUNCTION__, __LINE__, iic_obj, *iic_obj);
CY8C95XX_CHECK_EXP_NORTN(iic_obj != NULL, E_PAR);
CY8C95XX_CHECK_EXP_NORTN((dev == 0) || (dev == 1), E_PAR);
if (dev == 0) {
slvaddr = obj->slvaddr_io;
} else {
slvaddr = obj->slvaddr_eep;
}
data[0] = (uint8_t)(regaddr & 0xff);
/** make sure set the temp sensor's slave address */
ercd = iic_obj->iic_control(IIC_CMD_MST_SET_TAR_ADDR, CONV2VOID(slvaddr));
ercd = iic_obj->iic_control(IIC_CMD_MST_SET_NEXT_COND, CONV2VOID(IIC_MODE_RESTART));
ercd = iic_obj->iic_write(data, 1);
ercd = iic_obj->iic_control(IIC_CMD_MST_SET_NEXT_COND, CONV2VOID(IIC_MODE_STOP));
ercd = iic_obj->iic_write(val, len);
error_exit:
return ercd;
}
int32_t cy8c95xx_reg_read(CY8C95XX_DEF_PTR obj, uint8_t dev, uint8_t regaddr, uint8_t *val, uint8_t len)
{
int32_t ercd = E_OK;
uint8_t data[1];
uint32_t slvaddr;
DEV_IIC_PTR iic_obj = iic_get_dev(obj->i2c_id);
dbg_printf(DBG_MORE_INFO, "[%s]%d: iic_obj 0x%x -> 0x%x\r\n", __FUNCTION__, __LINE__, iic_obj, *iic_obj);
CY8C95XX_CHECK_EXP_NORTN(iic_obj != NULL, E_PAR);
CY8C95XX_CHECK_EXP_NORTN((dev == 0) || (dev == 1), E_PAR);
if (dev == 0) {
slvaddr = obj->slvaddr_io;
} else {
slvaddr = obj->slvaddr_eep;
}
data[0] = (uint8_t)(regaddr & 0xff);
/** make sure set the temp sensor's slave address */
ercd = iic_obj->iic_control(IIC_CMD_MST_SET_TAR_ADDR, CONV2VOID(slvaddr));
/** write register address then read register value */
ercd = iic_obj->iic_control(IIC_CMD_MST_SET_NEXT_COND, CONV2VOID(IIC_MODE_RESTART));
ercd = iic_obj->iic_write(data, 1);
ercd = iic_obj->iic_control(IIC_CMD_MST_SET_NEXT_COND, CONV2VOID(IIC_MODE_STOP));
ercd = iic_obj->iic_read(val, len);
error_exit:
return ercd;
}
int32_t cy8c95xx_readid(CY8C95XX_DEF_PTR obj, uint8_t *value)
{
int32_t ercd = E_OK;
uint8_t buffer_rx[1];
CY8C95XX_CHECK_EXP_NORTN(value != NULL, E_PAR);
CY8C95XX_CHECK_EXP_NORTN(cy8c95xx_reg_read(obj, CY8C95XX_DEV_IO, CY8C95XX_DEVICE_ID_REG, buffer_rx, 1) == E_OK, E_SYS);
*value = buffer_rx[0];
error_exit:
return ercd;
}
int32_t cy8c95xx_writeport(CY8C95XX_DEF_PTR obj, uint8_t port, uint8_t value)
{
int32_t ercd = E_OK;
uint8_t buffer_tx[1];
uint8_t val = 0;
CY8C95XX_CHECK_EXP_NORTN(port < CY8C95XX_PORT_NONE, E_PAR);
// Set port [0..7]
buffer_tx[0] = value;
CY8C95XX_CHECK_EXP_NORTN(cy8c95xx_reg_write(obj, CY8C95XX_DEV_IO, CY8C95XX_OUTPUT_PORT0_REG + port, buffer_tx, 1) == E_OK, E_SYS);
CY8C95XX_CHECK_EXP_NORTN(cy8c95xx_reg_read(obj, CY8C95XX_DEV_IO, CY8C95XX_OUTPUT_PORT0_REG + port, &val, 1) == E_OK, E_SYS);
CY8C95XX_CHECK_EXP_NORTN(val == value, E_OBJ);
error_exit:
return ercd;
}
int32_t cy8c95xx_readport(CY8C95XX_DEF_PTR obj, uint8_t port, uint8_t *value)
{
int32_t ercd = E_OK;
CY8C95XX_CHECK_EXP_NORTN(port < CY8C95XX_PORT_NONE, E_PAR);
CY8C95XX_CHECK_EXP_NORTN(cy8c95xx_reg_read(obj, CY8C95XX_DEV_IO, CY8C95XX_INPUT_PORT0_REG + port, value, 1) == E_OK, E_SYS);
error_exit:
return ercd;
}

View File

@@ -1,149 +0,0 @@
/* ------------------------------------------
* Copyright (c) 2017, Synopsys, Inc. All rights reserved.
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
* 1) Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2) Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
* 3) Neither the name of the Synopsys, Inc., nor the names of its contributors may
* be used to endorse or promote products derived from this software without
* specific prior written permission.
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
--------------------------------------------- */
#ifndef H_CY8C95XX
#define H_CY8C95XX
#define CY8C95XX_I2C_TIMEOUT (5000000)
// CY8C95xx Series Interface is a multi-port IO expander using I2C bus, on HSDK board
typedef enum {
CY8C95XX_DEV_IO = 0,
CY8C95XX_DEV_EEP
} CY8C95XX_DEV_T;
typedef enum {
CY8C95XX_PORT_0 = 0,
CY8C95XX_PORT_1,
CY8C95XX_PORT_2,
CY8C95XX_PORT_NONE
} CY8C95XX_PORT_T;
typedef enum {
CY8C95XX_PIN_0 = 0,
CY8C95XX_PIN_1,
CY8C95XX_PIN_2,
CY8C95XX_PIN_3,
CY8C95XX_PIN_4,
CY8C95XX_PIN_5,
CY8C95XX_PIN_6,
CY8C95XX_PIN_7,
CY8C95XX_PIN_NONE
} CY8C95XX_PIN_T;
typedef enum {
CY8C95XX_PWM_0 = 0,
CY8C95XX_PWM_1,
CY8C95XX_PWM_2,
CY8C95XX_PWM_3,
CY8C95XX_PWM_NONE
} CY8C95XX_PWM_T;
typedef enum {
CY8C95XX_PWMFREQ_100HZ = 0,
CY8C95XX_PWMFREQ_300HZ,
CY8C95XX_PWMFREQ_500HZ,
CY8C95XX_PWMFREQ_700HZ,
CY8C95XX_PWMFREQ_900HZ,
CY8C95XX_PWMFREQ_NONE
} CY8C95XX_PWMFREQ_T;
typedef enum {
CY8C95XX_ENABLE_WDE = 0,
CY8C95XX_ENABLE_EEE,
CY8C95XX_ENABLE_EERO,
CY8C95XX_ENABLE_NONE
} CY8C95XX_ENABLE_T;
typedef struct {
uint32_t i2c_id;
uint32_t slvaddr_io;
uint32_t slvaddr_eep;
} CY8C95XX_DEF, *CY8C95XX_DEF_PTR;
#define CY8C95XX_INPUT_PORT0_REG 0x00
#define CY8C95XX_INPUT_PORT1_REG 0x01
#define CY8C95XX_INPUT_PORT2_REG 0x02
#define CY8C95XX_INPUT_PORT3_REG 0x03
#define CY8C95XX_INPUT_PORT4_REG 0x04
#define CY8C95XX_INPUT_PORT5_REG 0x05
#define CY8C95XX_INPUT_PORT6_REG 0x06
#define CY8C95XX_INPUT_PORT7_REG 0x07
#define CY8C95XX_OUTPUT_PORT0_REG 0x08
#define CY8C95XX_OUTPUT_PORT1_REG 0x09
#define CY8C95XX_OUTPUT_PORT2_REG 0x0A
#define CY8C95XX_OUTPUT_PORT3_REG 0x0B
#define CY8C95XX_OUTPUT_PORT4_REG 0x0C
#define CY8C95XX_OUTPUT_PORT5_REG 0x0D
#define CY8C95XX_OUTPUT_PORT6_REG 0x0E
#define CY8C95XX_OUTPUT_PORT7_REG 0x0F
#define CY8C95XX_INTSTS_PORT0_REG 0x10
#define CY8C95XX_INTSTS_PORT1_REG 0x11
#define CY8C95XX_INTSTS_PORT2_REG 0x12
#define CY8C95XX_INTSTS_PORT3_REG 0x13
#define CY8C95XX_INTSTS_PORT4_REG 0x14
#define CY8C95XX_INTSTS_PORT5_REG 0x15
#define CY8C95XX_INTSTS_PORT6_REG 0x16
#define CY8C95XX_INTSTS_PORT7_REG 0x17
#define CY8C95XX_PORT_SELECT_REG 0x18
#define CY8C95XX_INTMSK_REG 0x19
#define CY8C95XX_PORT_SELECT_PWM 0x1A
#define CY8C95XX_PIN_DIRECTION_REG 0x1C
#define CY8C95XX_DRIVE_MODE_PU_REG 0x1D
#define CY8C95XX_DRIVE_MODE_PD_REG 0x1E
#define CY8C95XX_DRIVE_MODE_ODH_REG 0x1F
#define CY8C95XX_DRIVE_MODE_ODL_REG 0x20
#define CY8C95XX_DRIVE_MODE_S_REG 0x21
#define CY8C95XX_DRIVE_MODE_SS_REG 0x22
#define CY8C95XX_DRIVE_MODE_HZ_REG 0x23
#define CY8C95XX_PWM_SELECT 0x28
#define CY8C95XX_PWM_CONFIG 0x29
#define CY8C95XX_PWM_PERIOD 0x2A
#define CY8C95XX_PWM_PULSEWIDTH 0x2B
#define CY8C95XX_PWM_DIVIDER 0x2C
#define CY8C95XX_ENABLE_REG 0x2D
#define CY8C95XX_DEVICE_ID_REG 0x2E
#define CY8C95XX_COMMAND_REG 0x30
extern int32_t cy8c95xx_readid(CY8C95XX_DEF_PTR obj, uint8_t *value);
extern int32_t cy8c95xx_writeport(CY8C95XX_DEF_PTR obj, uint8_t port, uint8_t value);
extern int32_t cy8c95xx_readport(CY8C95XX_DEF_PTR obj, uint8_t port, uint8_t *value);
extern int32_t cy8c95xx_reg_write(CY8C95XX_DEF_PTR obj, uint8_t dev, uint8_t regaddr, uint8_t *val, uint8_t len);
extern int32_t cy8c95xx_reg_read(CY8C95XX_DEF_PTR obj, uint8_t dev, uint8_t regaddr, uint8_t *val, uint8_t len);
#endif /* H_CY8C95XX */

View File

@@ -1,2 +0,0 @@
DEV_CSRCDIR += $(EMBARC_ROOT)/device/peripheral/io/cy8c95xx
DEV_INCDIR += $(EMBARC_ROOT)/device/peripheral/io/cy8c95xx

View File

@@ -1,519 +0,0 @@
/* ------------------------------------------
* Copyright (c) 2018, 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.
*
--------------------------------------------- */
/*
$License:
Copyright (C) 2011 InvenSense Corporation, All Rights Reserved.
$
*/
#ifndef DMPKEY_H__
#define DMPKEY_H__
#define KEY_CFG_25 (0)
#define KEY_CFG_24 (KEY_CFG_25 + 1)
#define KEY_CFG_26 (KEY_CFG_24 + 1)
#define KEY_CFG_27 (KEY_CFG_26 + 1)
#define KEY_CFG_21 (KEY_CFG_27 + 1)
#define KEY_CFG_20 (KEY_CFG_21 + 1)
#define KEY_CFG_TAP4 (KEY_CFG_20 + 1)
#define KEY_CFG_TAP5 (KEY_CFG_TAP4 + 1)
#define KEY_CFG_TAP6 (KEY_CFG_TAP5 + 1)
#define KEY_CFG_TAP7 (KEY_CFG_TAP6 + 1)
#define KEY_CFG_TAP0 (KEY_CFG_TAP7 + 1)
#define KEY_CFG_TAP1 (KEY_CFG_TAP0 + 1)
#define KEY_CFG_TAP2 (KEY_CFG_TAP1 + 1)
#define KEY_CFG_TAP3 (KEY_CFG_TAP2 + 1)
#define KEY_CFG_TAP_QUANTIZE (KEY_CFG_TAP3 + 1)
#define KEY_CFG_TAP_JERK (KEY_CFG_TAP_QUANTIZE + 1)
#define KEY_CFG_DR_INT (KEY_CFG_TAP_JERK + 1)
#define KEY_CFG_AUTH (KEY_CFG_DR_INT + 1)
#define KEY_CFG_TAP_SAVE_ACCB (KEY_CFG_AUTH + 1)
#define KEY_CFG_TAP_CLEAR_STICKY (KEY_CFG_TAP_SAVE_ACCB + 1)
#define KEY_CFG_FIFO_ON_EVENT (KEY_CFG_TAP_CLEAR_STICKY + 1)
#define KEY_FCFG_ACCEL_INPUT (KEY_CFG_FIFO_ON_EVENT + 1)
#define KEY_FCFG_ACCEL_INIT (KEY_FCFG_ACCEL_INPUT + 1)
#define KEY_CFG_23 (KEY_FCFG_ACCEL_INIT + 1)
#define KEY_FCFG_1 (KEY_CFG_23 + 1)
#define KEY_FCFG_3 (KEY_FCFG_1 + 1)
#define KEY_FCFG_2 (KEY_FCFG_3 + 1)
#define KEY_CFG_3D (KEY_FCFG_2 + 1)
#define KEY_CFG_3B (KEY_CFG_3D + 1)
#define KEY_CFG_3C (KEY_CFG_3B + 1)
#define KEY_FCFG_5 (KEY_CFG_3C + 1)
#define KEY_FCFG_4 (KEY_FCFG_5 + 1)
#define KEY_FCFG_7 (KEY_FCFG_4 + 1)
#define KEY_FCFG_FSCALE (KEY_FCFG_7 + 1)
#define KEY_FCFG_AZ (KEY_FCFG_FSCALE + 1)
#define KEY_FCFG_6 (KEY_FCFG_AZ + 1)
#define KEY_FCFG_LSB4 (KEY_FCFG_6 + 1)
#define KEY_CFG_12 (KEY_FCFG_LSB4 + 1)
#define KEY_CFG_14 (KEY_CFG_12 + 1)
#define KEY_CFG_15 (KEY_CFG_14 + 1)
#define KEY_CFG_16 (KEY_CFG_15 + 1)
#define KEY_CFG_18 (KEY_CFG_16 + 1)
#define KEY_CFG_6 (KEY_CFG_18 + 1)
#define KEY_CFG_7 (KEY_CFG_6 + 1)
#define KEY_CFG_4 (KEY_CFG_7 + 1)
#define KEY_CFG_5 (KEY_CFG_4 + 1)
#define KEY_CFG_2 (KEY_CFG_5 + 1)
#define KEY_CFG_3 (KEY_CFG_2 + 1)
#define KEY_CFG_1 (KEY_CFG_3 + 1)
#define KEY_CFG_EXTERNAL (KEY_CFG_1 + 1)
#define KEY_CFG_8 (KEY_CFG_EXTERNAL + 1)
#define KEY_CFG_9 (KEY_CFG_8 + 1)
#define KEY_CFG_ORIENT_3 (KEY_CFG_9 + 1)
#define KEY_CFG_ORIENT_2 (KEY_CFG_ORIENT_3 + 1)
#define KEY_CFG_ORIENT_1 (KEY_CFG_ORIENT_2 + 1)
#define KEY_CFG_GYRO_SOURCE (KEY_CFG_ORIENT_1 + 1)
#define KEY_CFG_ORIENT_IRQ_1 (KEY_CFG_GYRO_SOURCE + 1)
#define KEY_CFG_ORIENT_IRQ_2 (KEY_CFG_ORIENT_IRQ_1 + 1)
#define KEY_CFG_ORIENT_IRQ_3 (KEY_CFG_ORIENT_IRQ_2 + 1)
#define KEY_FCFG_MAG_VAL (KEY_CFG_ORIENT_IRQ_3 + 1)
#define KEY_FCFG_MAG_MOV (KEY_FCFG_MAG_VAL + 1)
#define KEY_CFG_LP_QUAT (KEY_FCFG_MAG_MOV + 1)
/* MPU6050 keys */
#define KEY_CFG_ACCEL_FILTER (KEY_CFG_LP_QUAT + 1)
#define KEY_CFG_MOTION_BIAS (KEY_CFG_ACCEL_FILTER + 1)
#define KEY_TEMPLABEL (KEY_CFG_MOTION_BIAS + 1)
#define KEY_D_0_22 (KEY_TEMPLABEL + 1)
#define KEY_D_0_24 (KEY_D_0_22 + 1)
#define KEY_D_0_36 (KEY_D_0_24 + 1)
#define KEY_D_0_52 (KEY_D_0_36 + 1)
#define KEY_D_0_96 (KEY_D_0_52 + 1)
#define KEY_D_0_104 (KEY_D_0_96 + 1)
#define KEY_D_0_108 (KEY_D_0_104 + 1)
#define KEY_D_0_163 (KEY_D_0_108 + 1)
#define KEY_D_0_188 (KEY_D_0_163 + 1)
#define KEY_D_0_192 (KEY_D_0_188 + 1)
#define KEY_D_0_224 (KEY_D_0_192 + 1)
#define KEY_D_0_228 (KEY_D_0_224 + 1)
#define KEY_D_0_232 (KEY_D_0_228 + 1)
#define KEY_D_0_236 (KEY_D_0_232 + 1)
#define KEY_DMP_PREVPTAT (KEY_D_0_236 + 1)
#define KEY_D_1_2 (KEY_DMP_PREVPTAT + 1)
#define KEY_D_1_4 (KEY_D_1_2 + 1)
#define KEY_D_1_8 (KEY_D_1_4 + 1)
#define KEY_D_1_10 (KEY_D_1_8 + 1)
#define KEY_D_1_24 (KEY_D_1_10 + 1)
#define KEY_D_1_28 (KEY_D_1_24 + 1)
#define KEY_D_1_36 (KEY_D_1_28 + 1)
#define KEY_D_1_40 (KEY_D_1_36 + 1)
#define KEY_D_1_44 (KEY_D_1_40 + 1)
#define KEY_D_1_72 (KEY_D_1_44 + 1)
#define KEY_D_1_74 (KEY_D_1_72 + 1)
#define KEY_D_1_79 (KEY_D_1_74 + 1)
#define KEY_D_1_88 (KEY_D_1_79 + 1)
#define KEY_D_1_90 (KEY_D_1_88 + 1)
#define KEY_D_1_92 (KEY_D_1_90 + 1)
#define KEY_D_1_96 (KEY_D_1_92 + 1)
#define KEY_D_1_98 (KEY_D_1_96 + 1)
#define KEY_D_1_100 (KEY_D_1_98 + 1)
#define KEY_D_1_106 (KEY_D_1_100 + 1)
#define KEY_D_1_108 (KEY_D_1_106 + 1)
#define KEY_D_1_112 (KEY_D_1_108 + 1)
#define KEY_D_1_128 (KEY_D_1_112 + 1)
#define KEY_D_1_152 (KEY_D_1_128 + 1)
#define KEY_D_1_160 (KEY_D_1_152 + 1)
#define KEY_D_1_168 (KEY_D_1_160 + 1)
#define KEY_D_1_175 (KEY_D_1_168 + 1)
#define KEY_D_1_176 (KEY_D_1_175 + 1)
#define KEY_D_1_178 (KEY_D_1_176 + 1)
#define KEY_D_1_179 (KEY_D_1_178 + 1)
#define KEY_D_1_218 (KEY_D_1_179 + 1)
#define KEY_D_1_232 (KEY_D_1_218 + 1)
#define KEY_D_1_236 (KEY_D_1_232 + 1)
#define KEY_D_1_240 (KEY_D_1_236 + 1)
#define KEY_D_1_244 (KEY_D_1_240 + 1)
#define KEY_D_1_250 (KEY_D_1_244 + 1)
#define KEY_D_1_252 (KEY_D_1_250 + 1)
#define KEY_D_2_12 (KEY_D_1_252 + 1)
#define KEY_D_2_96 (KEY_D_2_12 + 1)
#define KEY_D_2_108 (KEY_D_2_96 + 1)
#define KEY_D_2_208 (KEY_D_2_108 + 1)
#define KEY_FLICK_MSG (KEY_D_2_208 + 1)
#define KEY_FLICK_COUNTER (KEY_FLICK_MSG + 1)
#define KEY_FLICK_LOWER (KEY_FLICK_COUNTER + 1)
#define KEY_CFG_FLICK_IN (KEY_FLICK_LOWER + 1)
#define KEY_FLICK_UPPER (KEY_CFG_FLICK_IN + 1)
#define KEY_CGNOTICE_INTR (KEY_FLICK_UPPER + 1)
#define KEY_D_2_224 (KEY_CGNOTICE_INTR + 1)
#define KEY_D_2_244 (KEY_D_2_224 + 1)
#define KEY_D_2_248 (KEY_D_2_244 + 1)
#define KEY_D_2_252 (KEY_D_2_248 + 1)
#define KEY_D_GYRO_BIAS_X (KEY_D_2_252 + 1)
#define KEY_D_GYRO_BIAS_Y (KEY_D_GYRO_BIAS_X + 1)
#define KEY_D_GYRO_BIAS_Z (KEY_D_GYRO_BIAS_Y + 1)
#define KEY_D_ACC_BIAS_X (KEY_D_GYRO_BIAS_Z + 1)
#define KEY_D_ACC_BIAS_Y (KEY_D_ACC_BIAS_X + 1)
#define KEY_D_ACC_BIAS_Z (KEY_D_ACC_BIAS_Y + 1)
#define KEY_D_GYRO_ENABLE (KEY_D_ACC_BIAS_Z + 1)
#define KEY_D_ACCEL_ENABLE (KEY_D_GYRO_ENABLE + 1)
#define KEY_D_QUAT_ENABLE (KEY_D_ACCEL_ENABLE + 1)
#define KEY_D_OUTPUT_ENABLE (KEY_D_QUAT_ENABLE + 1)
#define KEY_D_CR_TIME_G (KEY_D_OUTPUT_ENABLE + 1)
#define KEY_D_CR_TIME_A (KEY_D_CR_TIME_G + 1)
#define KEY_D_CR_TIME_Q (KEY_D_CR_TIME_A + 1)
#define KEY_D_CS_TAX (KEY_D_CR_TIME_Q + 1)
#define KEY_D_CS_TAY (KEY_D_CS_TAX + 1)
#define KEY_D_CS_TAZ (KEY_D_CS_TAY + 1)
#define KEY_D_CS_TGX (KEY_D_CS_TAZ + 1)
#define KEY_D_CS_TGY (KEY_D_CS_TGX + 1)
#define KEY_D_CS_TGZ (KEY_D_CS_TGY + 1)
#define KEY_D_CS_TQ0 (KEY_D_CS_TGZ + 1)
#define KEY_D_CS_TQ1 (KEY_D_CS_TQ0 + 1)
#define KEY_D_CS_TQ2 (KEY_D_CS_TQ1 + 1)
#define KEY_D_CS_TQ3 (KEY_D_CS_TQ2 + 1)
/* Compass keys */
#define KEY_CPASS_BIAS_X (KEY_D_CS_TQ3 + 1)
#define KEY_CPASS_BIAS_Y (KEY_CPASS_BIAS_X + 1)
#define KEY_CPASS_BIAS_Z (KEY_CPASS_BIAS_Y + 1)
#define KEY_CPASS_MTX_00 (KEY_CPASS_BIAS_Z + 1)
#define KEY_CPASS_MTX_01 (KEY_CPASS_MTX_00 + 1)
#define KEY_CPASS_MTX_02 (KEY_CPASS_MTX_01 + 1)
#define KEY_CPASS_MTX_10 (KEY_CPASS_MTX_02 + 1)
#define KEY_CPASS_MTX_11 (KEY_CPASS_MTX_10 + 1)
#define KEY_CPASS_MTX_12 (KEY_CPASS_MTX_11 + 1)
#define KEY_CPASS_MTX_20 (KEY_CPASS_MTX_12 + 1)
#define KEY_CPASS_MTX_21 (KEY_CPASS_MTX_20 + 1)
#define KEY_CPASS_MTX_22 (KEY_CPASS_MTX_21 + 1)
/* Gesture Keys */
#define KEY_DMP_TAPW_MIN (KEY_CPASS_MTX_22 + 1)
#define KEY_DMP_TAP_THR_X (KEY_DMP_TAPW_MIN + 1)
#define KEY_DMP_TAP_THR_Y (KEY_DMP_TAP_THR_X + 1)
#define KEY_DMP_TAP_THR_Z (KEY_DMP_TAP_THR_Y + 1)
#define KEY_DMP_SH_TH_Y (KEY_DMP_TAP_THR_Z + 1)
#define KEY_DMP_SH_TH_X (KEY_DMP_SH_TH_Y + 1)
#define KEY_DMP_SH_TH_Z (KEY_DMP_SH_TH_X + 1)
#define KEY_DMP_ORIENT (KEY_DMP_SH_TH_Z + 1)
#define KEY_D_ACT0 (KEY_DMP_ORIENT + 1)
#define KEY_D_ACSX (KEY_D_ACT0 + 1)
#define KEY_D_ACSY (KEY_D_ACSX + 1)
#define KEY_D_ACSZ (KEY_D_ACSY + 1)
#define KEY_X_GRT_Y_TMP (KEY_D_ACSZ + 1)
#define KEY_SKIP_X_GRT_Y_TMP (KEY_X_GRT_Y_TMP + 1)
#define KEY_SKIP_END_COMPARE (KEY_SKIP_X_GRT_Y_TMP + 1)
#define KEY_END_COMPARE_Y_X_TMP2 (KEY_SKIP_END_COMPARE + 1)
#define KEY_CFG_ANDROID_ORIENT_INT (KEY_END_COMPARE_Y_X_TMP2 + 1)
#define KEY_NO_ORIENT_INTERRUPT (KEY_CFG_ANDROID_ORIENT_INT + 1)
#define KEY_END_COMPARE_Y_X_TMP (KEY_NO_ORIENT_INTERRUPT + 1)
#define KEY_END_ORIENT_1 (KEY_END_COMPARE_Y_X_TMP + 1)
#define KEY_END_COMPARE_Y_X (KEY_END_ORIENT_1 + 1)
#define KEY_END_ORIENT (KEY_END_COMPARE_Y_X + 1)
#define KEY_X_GRT_Y (KEY_END_ORIENT + 1)
#define KEY_NOT_TIME_MINUS_1 (KEY_X_GRT_Y + 1)
#define KEY_END_COMPARE_Y_X_TMP3 (KEY_NOT_TIME_MINUS_1 + 1)
#define KEY_X_GRT_Y_TMP2 (KEY_END_COMPARE_Y_X_TMP3 + 1)
/* Authenticate Keys */
#define KEY_D_AUTH_OUT (KEY_X_GRT_Y_TMP2 + 1)
#define KEY_D_AUTH_IN (KEY_D_AUTH_OUT + 1)
#define KEY_D_AUTH_A (KEY_D_AUTH_IN + 1)
#define KEY_D_AUTH_B (KEY_D_AUTH_A + 1)
/* Pedometer standalone only keys */
#define KEY_D_PEDSTD_BP_B (KEY_D_AUTH_B + 1)
#define KEY_D_PEDSTD_HP_A (KEY_D_PEDSTD_BP_B + 1)
#define KEY_D_PEDSTD_HP_B (KEY_D_PEDSTD_HP_A + 1)
#define KEY_D_PEDSTD_BP_A4 (KEY_D_PEDSTD_HP_B + 1)
#define KEY_D_PEDSTD_BP_A3 (KEY_D_PEDSTD_BP_A4 + 1)
#define KEY_D_PEDSTD_BP_A2 (KEY_D_PEDSTD_BP_A3 + 1)
#define KEY_D_PEDSTD_BP_A1 (KEY_D_PEDSTD_BP_A2 + 1)
#define KEY_D_PEDSTD_INT_THRSH (KEY_D_PEDSTD_BP_A1 + 1)
#define KEY_D_PEDSTD_CLIP (KEY_D_PEDSTD_INT_THRSH + 1)
#define KEY_D_PEDSTD_SB (KEY_D_PEDSTD_CLIP + 1)
#define KEY_D_PEDSTD_SB_TIME (KEY_D_PEDSTD_SB + 1)
#define KEY_D_PEDSTD_PEAKTHRSH (KEY_D_PEDSTD_SB_TIME + 1)
#define KEY_D_PEDSTD_TIML (KEY_D_PEDSTD_PEAKTHRSH + 1)
#define KEY_D_PEDSTD_TIMH (KEY_D_PEDSTD_TIML + 1)
#define KEY_D_PEDSTD_PEAK (KEY_D_PEDSTD_TIMH + 1)
#define KEY_D_PEDSTD_TIMECTR (KEY_D_PEDSTD_PEAK + 1)
#define KEY_D_PEDSTD_STEPCTR (KEY_D_PEDSTD_TIMECTR + 1)
#define KEY_D_PEDSTD_WALKTIME (KEY_D_PEDSTD_STEPCTR + 1)
#define KEY_D_PEDSTD_DECI (KEY_D_PEDSTD_WALKTIME + 1)
/*Host Based No Motion*/
#define KEY_D_HOST_NO_MOT (KEY_D_PEDSTD_DECI + 1)
/* EIS keys */
#define KEY_P_EIS_FIFO_FOOTER (KEY_D_HOST_NO_MOT + 1)
#define KEY_P_EIS_FIFO_YSHIFT (KEY_P_EIS_FIFO_FOOTER + 1)
#define KEY_P_EIS_DATA_RATE (KEY_P_EIS_FIFO_YSHIFT + 1)
#define KEY_P_EIS_FIFO_XSHIFT (KEY_P_EIS_DATA_RATE + 1)
#define KEY_P_EIS_FIFO_SYNC (KEY_P_EIS_FIFO_XSHIFT + 1)
#define KEY_P_EIS_FIFO_ZSHIFT (KEY_P_EIS_FIFO_SYNC + 1)
#define KEY_P_EIS_FIFO_READY (KEY_P_EIS_FIFO_ZSHIFT + 1)
#define KEY_DMP_FOOTER (KEY_P_EIS_FIFO_READY + 1)
#define KEY_DMP_INTX_HC (KEY_DMP_FOOTER + 1)
#define KEY_DMP_INTX_PH (KEY_DMP_INTX_HC + 1)
#define KEY_DMP_INTX_SH (KEY_DMP_INTX_PH + 1)
#define KEY_DMP_AINV_SH (KEY_DMP_INTX_SH + 1)
#define KEY_DMP_A_INV_XH (KEY_DMP_AINV_SH + 1)
#define KEY_DMP_AINV_PH (KEY_DMP_A_INV_XH + 1)
#define KEY_DMP_CTHX_H (KEY_DMP_AINV_PH + 1)
#define KEY_DMP_CTHY_H (KEY_DMP_CTHX_H + 1)
#define KEY_DMP_CTHZ_H (KEY_DMP_CTHY_H + 1)
#define KEY_DMP_NCTHX_H (KEY_DMP_CTHZ_H + 1)
#define KEY_DMP_NCTHY_H (KEY_DMP_NCTHX_H + 1)
#define KEY_DMP_NCTHZ_H (KEY_DMP_NCTHY_H + 1)
#define KEY_DMP_CTSQ_XH (KEY_DMP_NCTHZ_H + 1)
#define KEY_DMP_CTSQ_YH (KEY_DMP_CTSQ_XH + 1)
#define KEY_DMP_CTSQ_ZH (KEY_DMP_CTSQ_YH + 1)
#define KEY_DMP_INTX_H (KEY_DMP_CTSQ_ZH + 1)
#define KEY_DMP_INTY_H (KEY_DMP_INTX_H + 1)
#define KEY_DMP_INTZ_H (KEY_DMP_INTY_H + 1)
// #define KEY_DMP_HPX_H (KEY_DMP_INTZ_H + 1)
// #define KEY_DMP_HPY_H (KEY_DMP_HPX_H + 1)
// #define KEY_DMP_HPZ_H (KEY_DMP_HPY_H + 1)
/* Stream keys */
#define KEY_STREAM_P_GYRO_Z (KEY_DMP_INTZ_H + 1)
#define KEY_STREAM_P_GYRO_Y (KEY_STREAM_P_GYRO_Z + 1)
#define KEY_STREAM_P_GYRO_X (KEY_STREAM_P_GYRO_Y + 1)
#define KEY_STREAM_P_TEMP (KEY_STREAM_P_GYRO_X + 1)
#define KEY_STREAM_P_AUX_Y (KEY_STREAM_P_TEMP + 1)
#define KEY_STREAM_P_AUX_X (KEY_STREAM_P_AUX_Y + 1)
#define KEY_STREAM_P_AUX_Z (KEY_STREAM_P_AUX_X + 1)
#define KEY_STREAM_P_ACCEL_Y (KEY_STREAM_P_AUX_Z + 1)
#define KEY_STREAM_P_ACCEL_X (KEY_STREAM_P_ACCEL_Y + 1)
#define KEY_STREAM_P_FOOTER (KEY_STREAM_P_ACCEL_X + 1)
#define KEY_STREAM_P_ACCEL_Z (KEY_STREAM_P_FOOTER + 1)
#define NUM_KEYS (KEY_STREAM_P_ACCEL_Z + 1)
typedef struct {
unsigned short key;
unsigned short addr;
} tKeyLabel;
#define DINA0A 0x0a
#define DINA22 0x22
#define DINA42 0x42
#define DINA5A 0x5a
#define DINA06 0x06
#define DINA0E 0x0e
#define DINA16 0x16
#define DINA1E 0x1e
#define DINA26 0x26
#define DINA2E 0x2e
#define DINA36 0x36
#define DINA3E 0x3e
#define DINA46 0x46
#define DINA4E 0x4e
#define DINA56 0x56
#define DINA5E 0x5e
#define DINA66 0x66
#define DINA6E 0x6e
#define DINA76 0x76
#define DINA7E 0x7e
#define DINA00 0x00
#define DINA08 0x08
#define DINA10 0x10
#define DINA18 0x18
#define DINA20 0x20
#define DINA28 0x28
#define DINA30 0x30
#define DINA38 0x38
#define DINA40 0x40
#define DINA48 0x48
#define DINA50 0x50
#define DINA58 0x58
#define DINA60 0x60
#define DINA68 0x68
#define DINA70 0x70
#define DINA78 0x78
#define DINA04 0x04
#define DINA0C 0x0c
#define DINA14 0x14
#define DINA1C 0x1C
#define DINA24 0x24
#define DINA2C 0x2c
#define DINA34 0x34
#define DINA3C 0x3c
#define DINA44 0x44
#define DINA4C 0x4c
#define DINA54 0x54
#define DINA5C 0x5c
#define DINA64 0x64
#define DINA6C 0x6c
#define DINA74 0x74
#define DINA7C 0x7c
#define DINA01 0x01
#define DINA09 0x09
#define DINA11 0x11
#define DINA19 0x19
#define DINA21 0x21
#define DINA29 0x29
#define DINA31 0x31
#define DINA39 0x39
#define DINA41 0x41
#define DINA49 0x49
#define DINA51 0x51
#define DINA59 0x59
#define DINA61 0x61
#define DINA69 0x69
#define DINA71 0x71
#define DINA79 0x79
#define DINA25 0x25
#define DINA2D 0x2d
#define DINA35 0x35
#define DINA3D 0x3d
#define DINA4D 0x4d
#define DINA55 0x55
#define DINA5D 0x5D
#define DINA6D 0x6d
#define DINA75 0x75
#define DINA7D 0x7d
#define DINADC 0xdc
#define DINAF2 0xf2
#define DINAAB 0xab
#define DINAAA 0xaa
#define DINAF1 0xf1
#define DINADF 0xdf
#define DINADA 0xda
#define DINAB1 0xb1
#define DINAB9 0xb9
#define DINAF3 0xf3
#define DINA8B 0x8b
#define DINAA3 0xa3
#define DINA91 0x91
#define DINAB6 0xb6
#define DINAB4 0xb4
#define DINC00 0x00
#define DINC01 0x01
#define DINC02 0x02
#define DINC03 0x03
#define DINC08 0x08
#define DINC09 0x09
#define DINC0A 0x0a
#define DINC0B 0x0b
#define DINC10 0x10
#define DINC11 0x11
#define DINC12 0x12
#define DINC13 0x13
#define DINC18 0x18
#define DINC19 0x19
#define DINC1A 0x1a
#define DINC1B 0x1b
#define DINC20 0x20
#define DINC21 0x21
#define DINC22 0x22
#define DINC23 0x23
#define DINC28 0x28
#define DINC29 0x29
#define DINC2A 0x2a
#define DINC2B 0x2b
#define DINC30 0x30
#define DINC31 0x31
#define DINC32 0x32
#define DINC33 0x33
#define DINC38 0x38
#define DINC39 0x39
#define DINC3A 0x3a
#define DINC3B 0x3b
#define DINC40 0x40
#define DINC41 0x41
#define DINC42 0x42
#define DINC43 0x43
#define DINC48 0x48
#define DINC49 0x49
#define DINC4A 0x4a
#define DINC4B 0x4b
#define DINC50 0x50
#define DINC51 0x51
#define DINC52 0x52
#define DINC53 0x53
#define DINC58 0x58
#define DINC59 0x59
#define DINC5A 0x5a
#define DINC5B 0x5b
#define DINC60 0x60
#define DINC61 0x61
#define DINC62 0x62
#define DINC63 0x63
#define DINC68 0x68
#define DINC69 0x69
#define DINC6A 0x6a
#define DINC6B 0x6b
#define DINC70 0x70
#define DINC71 0x71
#define DINC72 0x72
#define DINC73 0x73
#define DINC78 0x78
#define DINC79 0x79
#define DINC7A 0x7a
#define DINC7B 0x7b
#define DIND40 0x40
#define DINA80 0x80
#define DINA90 0x90
#define DINAA0 0xa0
#define DINAC9 0xc9
#define DINACB 0xcb
#define DINACD 0xcd
#define DINACF 0xcf
#define DINAC8 0xc8
#define DINACA 0xca
#define DINACC 0xcc
#define DINACE 0xce
#define DINAD8 0xd8
#define DINADD 0xdd
#define DINAF8 0xf0
#define DINAFE 0xfe
#define DINBF8 0xf8
#define DINAC0 0xb0
#define DINAC1 0xb1
#define DINAC2 0xb4
#define DINAC3 0xb5
#define DINAC4 0xb8
#define DINAC5 0xb9
#define DINBC0 0xc0
#define DINBC2 0xc2
#define DINBC4 0xc4
#define DINBC6 0xc6
#endif // DMPKEY_H__

View File

@@ -1,293 +0,0 @@
/* ------------------------------------------
* Copyright (c) 2018, 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.
*
--------------------------------------------- */
/*
$License:
Copyright (C) 2011 InvenSense Corporation, All Rights Reserved.
$
*/
#ifndef DMPMAP_H
#define DMPMAP_H
#ifdef __cplusplus
extern "C"
{
#endif
#define DMP_PTAT 0
#define DMP_XGYR 2
#define DMP_YGYR 4
#define DMP_ZGYR 6
#define DMP_XACC 8
#define DMP_YACC 10
#define DMP_ZACC 12
#define DMP_ADC1 14
#define DMP_ADC2 16
#define DMP_ADC3 18
#define DMP_BIASUNC 20
#define DMP_FIFORT 22
#define DMP_INVGSFH 24
#define DMP_INVGSFL 26
#define DMP_1H 28
#define DMP_1L 30
#define DMP_BLPFSTCH 32
#define DMP_BLPFSTCL 34
#define DMP_BLPFSXH 36
#define DMP_BLPFSXL 38
#define DMP_BLPFSYH 40
#define DMP_BLPFSYL 42
#define DMP_BLPFSZH 44
#define DMP_BLPFSZL 46
#define DMP_BLPFMTC 48
#define DMP_SMC 50
#define DMP_BLPFMXH 52
#define DMP_BLPFMXL 54
#define DMP_BLPFMYH 56
#define DMP_BLPFMYL 58
#define DMP_BLPFMZH 60
#define DMP_BLPFMZL 62
#define DMP_BLPFC 64
#define DMP_SMCTH 66
#define DMP_0H2 68
#define DMP_0L2 70
#define DMP_BERR2H 72
#define DMP_BERR2L 74
#define DMP_BERR2NH 76
#define DMP_SMCINC 78
#define DMP_ANGVBXH 80
#define DMP_ANGVBXL 82
#define DMP_ANGVBYH 84
#define DMP_ANGVBYL 86
#define DMP_ANGVBZH 88
#define DMP_ANGVBZL 90
#define DMP_BERR1H 92
#define DMP_BERR1L 94
#define DMP_ATCH 96
#define DMP_BIASUNCSF 98
#define DMP_ACT2H 100
#define DMP_ACT2L 102
#define DMP_GSFH 104
#define DMP_GSFL 106
#define DMP_GH 108
#define DMP_GL 110
#define DMP_0_5H 112
#define DMP_0_5L 114
#define DMP_0_0H 116
#define DMP_0_0L 118
#define DMP_1_0H 120
#define DMP_1_0L 122
#define DMP_1_5H 124
#define DMP_1_5L 126
#define DMP_TMP1AH 128
#define DMP_TMP1AL 130
#define DMP_TMP2AH 132
#define DMP_TMP2AL 134
#define DMP_TMP3AH 136
#define DMP_TMP3AL 138
#define DMP_TMP4AH 140
#define DMP_TMP4AL 142
#define DMP_XACCW 144
#define DMP_TMP5 146
#define DMP_XACCB 148
#define DMP_TMP8 150
#define DMP_YACCB 152
#define DMP_TMP9 154
#define DMP_ZACCB 156
#define DMP_TMP10 158
#define DMP_DZH 160
#define DMP_DZL 162
#define DMP_XGCH 164
#define DMP_XGCL 166
#define DMP_YGCH 168
#define DMP_YGCL 170
#define DMP_ZGCH 172
#define DMP_ZGCL 174
#define DMP_YACCW 176
#define DMP_TMP7 178
#define DMP_AFB1H 180
#define DMP_AFB1L 182
#define DMP_AFB2H 184
#define DMP_AFB2L 186
#define DMP_MAGFBH 188
#define DMP_MAGFBL 190
#define DMP_QT1H 192
#define DMP_QT1L 194
#define DMP_QT2H 196
#define DMP_QT2L 198
#define DMP_QT3H 200
#define DMP_QT3L 202
#define DMP_QT4H 204
#define DMP_QT4L 206
#define DMP_CTRL1H 208
#define DMP_CTRL1L 210
#define DMP_CTRL2H 212
#define DMP_CTRL2L 214
#define DMP_CTRL3H 216
#define DMP_CTRL3L 218
#define DMP_CTRL4H 220
#define DMP_CTRL4L 222
#define DMP_CTRLS1 224
#define DMP_CTRLSF1 226
#define DMP_CTRLS2 228
#define DMP_CTRLSF2 230
#define DMP_CTRLS3 232
#define DMP_CTRLSFNLL 234
#define DMP_CTRLS4 236
#define DMP_CTRLSFNL2 238
#define DMP_CTRLSFNL 240
#define DMP_TMP30 242
#define DMP_CTRLSFJT 244
#define DMP_TMP31 246
#define DMP_TMP11 248
#define DMP_CTRLSF2_2 250
#define DMP_TMP12 252
#define DMP_CTRLSF1_2 254
#define DMP_PREVPTAT 256
#define DMP_ACCZB 258
#define DMP_ACCXB 264
#define DMP_ACCYB 266
#define DMP_1HB 272
#define DMP_1LB 274
#define DMP_0H 276
#define DMP_0L 278
#define DMP_ASR22H 280
#define DMP_ASR22L 282
#define DMP_ASR6H 284
#define DMP_ASR6L 286
#define DMP_TMP13 288
#define DMP_TMP14 290
#define DMP_FINTXH 292
#define DMP_FINTXL 294
#define DMP_FINTYH 296
#define DMP_FINTYL 298
#define DMP_FINTZH 300
#define DMP_FINTZL 302
#define DMP_TMP1BH 304
#define DMP_TMP1BL 306
#define DMP_TMP2BH 308
#define DMP_TMP2BL 310
#define DMP_TMP3BH 312
#define DMP_TMP3BL 314
#define DMP_TMP4BH 316
#define DMP_TMP4BL 318
#define DMP_STXG 320
#define DMP_ZCTXG 322
#define DMP_STYG 324
#define DMP_ZCTYG 326
#define DMP_STZG 328
#define DMP_ZCTZG 330
#define DMP_CTRLSFJT2 332
#define DMP_CTRLSFJTCNT 334
#define DMP_PVXG 336
#define DMP_TMP15 338
#define DMP_PVYG 340
#define DMP_TMP16 342
#define DMP_PVZG 344
#define DMP_TMP17 346
#define DMP_MNMFLAGH 352
#define DMP_MNMFLAGL 354
#define DMP_MNMTMH 356
#define DMP_MNMTML 358
#define DMP_MNMTMTHRH 360
#define DMP_MNMTMTHRL 362
#define DMP_MNMTHRH 364
#define DMP_MNMTHRL 366
#define DMP_ACCQD4H 368
#define DMP_ACCQD4L 370
#define DMP_ACCQD5H 372
#define DMP_ACCQD5L 374
#define DMP_ACCQD6H 376
#define DMP_ACCQD6L 378
#define DMP_ACCQD7H 380
#define DMP_ACCQD7L 382
#define DMP_ACCQD0H 384
#define DMP_ACCQD0L 386
#define DMP_ACCQD1H 388
#define DMP_ACCQD1L 390
#define DMP_ACCQD2H 392
#define DMP_ACCQD2L 394
#define DMP_ACCQD3H 396
#define DMP_ACCQD3L 398
#define DMP_XN2H 400
#define DMP_XN2L 402
#define DMP_XN1H 404
#define DMP_XN1L 406
#define DMP_YN2H 408
#define DMP_YN2L 410
#define DMP_YN1H 412
#define DMP_YN1L 414
#define DMP_YH 416
#define DMP_YL 418
#define DMP_B0H 420
#define DMP_B0L 422
#define DMP_A1H 424
#define DMP_A1L 426
#define DMP_A2H 428
#define DMP_A2L 430
#define DMP_SEM1 432
#define DMP_FIFOCNT 434
#define DMP_SH_TH_X 436
#define DMP_PACKET 438
#define DMP_SH_TH_Y 440
#define DMP_FOOTER 442
#define DMP_SH_TH_Z 444
#define DMP_TEMP29 448
#define DMP_TEMP30 450
#define DMP_XACCB_PRE 452
#define DMP_XACCB_PREL 454
#define DMP_YACCB_PRE 456
#define DMP_YACCB_PREL 458
#define DMP_ZACCB_PRE 460
#define DMP_ZACCB_PREL 462
#define DMP_TMP22 464
#define DMP_TAP_TIMER 466
#define DMP_TAP_THX 468
#define DMP_TAP_THY 472
#define DMP_TAP_THZ 476
#define DMP_TAPW_MIN 478
#define DMP_TMP25 480
#define DMP_TMP26 482
#define DMP_TMP27 484
#define DMP_TMP28 486
#define DMP_ORIENT 488
#define DMP_THRSH 490
#define DMP_ENDIANH 492
#define DMP_ENDIANL 494
#define DMP_BLPFNMTCH 496
#define DMP_BLPFNMTCL 498
#define DMP_BLPFNMXH 500
#define DMP_BLPFNMXL 502
#define DMP_BLPFNMYH 504
#define DMP_BLPFNMYL 506
#define DMP_BLPFNMZH 508
#define DMP_BLPFNMZL 510
#ifdef __cplusplus
}
#endif
#endif // DMPMAP_H

View File

@@ -1,161 +0,0 @@
/* ------------------------------------------
* Copyright (c) 2018, 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.
*
--------------------------------------------- */
/*
$License:
Copyright (C) 2011-2012 InvenSense Corporation, All Rights Reserved.
See included License.txt for License information.
$
*/
/**
* @addtogroup DRIVERS Sensor Driver Layer
* @brief Hardware drivers to communicate with sensors via I2C.
*
* @{
* @file inv_mpu.h
* @brief An I2C-based driver for Invensense gyroscopes.
* @details This driver currently works for the following devices:
* MPU6050
* MPU6500
* MPU9150 (or MPU6050 w/ AK8975 on the auxiliary bus)
* MPU9250 (or MPU6500 w/ AK8963 on the auxiliary bus)
*/
#ifndef _INV_MPU_H_
#define _INV_MPU_H_
#define INV_X_GYRO (0x40)
#define INV_Y_GYRO (0x20)
#define INV_Z_GYRO (0x10)
#define INV_XYZ_GYRO (INV_X_GYRO | INV_Y_GYRO | INV_Z_GYRO)
#define INV_XYZ_ACCEL (0x08)
#define INV_XYZ_COMPASS (0x01)
struct int_param_s {
#if defined EMPL_TARGET_MSP430 || defined MOTION_DRIVER_TARGET_MSP430
void (*cb)(void);
unsigned short pin;
unsigned char lp_exit;
unsigned char active_low;
#elif defined EMPL_TARGET_UC3L0
unsigned long pin;
void (*cb)(volatile void *);
void *arg;
#endif
};
#define MPU_INT_STATUS_DATA_READY (0x0001)
#define MPU_INT_STATUS_DMP (0x0002)
#define MPU_INT_STATUS_PLL_READY (0x0004)
#define MPU_INT_STATUS_I2C_MST (0x0008)
#define MPU_INT_STATUS_FIFO_OVERFLOW (0x0010)
#define MPU_INT_STATUS_ZMOT (0x0020)
#define MPU_INT_STATUS_MOT (0x0040)
#define MPU_INT_STATUS_FREE_FALL (0x0080)
#define MPU_INT_STATUS_DMP_0 (0x0100)
#define MPU_INT_STATUS_DMP_1 (0x0200)
#define MPU_INT_STATUS_DMP_2 (0x0400)
#define MPU_INT_STATUS_DMP_3 (0x0800)
#define MPU_INT_STATUS_DMP_4 (0x1000)
#define MPU_INT_STATUS_DMP_5 (0x2000)
/* Set up APIs */
// int mpu_init(struct int_param_s *int_param);
int mpu_init();// struct int_param_s *int_param);
int mpu_init_slave(void);
int mpu_set_bypass(unsigned char bypass_on);
/* Configuration APIs */
int mpu_lp_accel_mode(unsigned short rate);
int mpu_lp_motion_interrupt(unsigned short thresh, unsigned char time,
unsigned char lpa_freq);
int mpu_set_int_level(unsigned char active_low);
int mpu_set_int_latched(unsigned char enable);
int mpu_set_dmp_state(unsigned char enable);
int mpu_get_dmp_state(unsigned char *enabled);
int mpu_get_lpf(unsigned short *lpf);
int mpu_set_lpf(unsigned short lpf);
int mpu_get_gyro_fsr(unsigned short *fsr);
int mpu_set_gyro_fsr(unsigned short fsr);
int mpu_get_accel_fsr(unsigned char *fsr);
int mpu_set_accel_fsr(unsigned char fsr);
int mpu_get_compass_fsr(unsigned short *fsr);
int mpu_get_gyro_sens(float *sens);
int mpu_get_accel_sens(unsigned short *sens);
int mpu_get_sample_rate(unsigned short *rate);
int mpu_set_sample_rate(unsigned short rate);
int mpu_get_compass_sample_rate(unsigned short *rate);
int mpu_set_compass_sample_rate(unsigned short rate);
int mpu_get_fifo_config(unsigned char *sensors);
int mpu_configure_fifo(unsigned char sensors);
int mpu_get_power_state(unsigned char *power_on);
int mpu_set_sensors(unsigned char sensors);
int mpu_read_6500_accel_bias(long *accel_bias);
int mpu_set_gyro_bias_reg(long *gyro_bias);
int mpu_set_accel_bias_6500_reg(const long *accel_bias);
int mpu_read_6050_accel_bias(long *accel_bias);
int mpu_set_accel_bias_6050_reg(const long *accel_bias);
/* Data getter/setter APIs */
int mpu_get_gyro_reg(short *data, unsigned long *timestamp);
int mpu_get_accel_reg(short *data, unsigned long *timestamp);
int mpu_get_compass_reg(short *data, unsigned long *timestamp);
int mpu_get_temperature(long *data, unsigned long *timestamp);
int mpu_get_int_status(short *status);
int mpu_read_fifo(short *gyro, short *accel, unsigned long *timestamp,
unsigned char *sensors, unsigned char *more);
int mpu_read_fifo_stream(unsigned short length, unsigned char *data,
unsigned char *more);
int mpu_reset_fifo(void);
int mpu_write_mem(unsigned short mem_addr, unsigned short length,
unsigned char *data);
int mpu_read_mem(unsigned short mem_addr, unsigned short length,
unsigned char *data);
int mpu_load_firmware(unsigned short length, const unsigned char *firmware,
unsigned short start_addr, unsigned short sample_rate);
int mpu_reg_dump(void);
int mpu_read_reg(unsigned char reg, unsigned char *data);
int mpu_run_self_test(long *gyro, long *accel);
int mpu_run_6500_self_test(long *gyro, long *accel, unsigned char debug);
int mpu_register_tap_cb(void (*func)(unsigned char, unsigned char));
#endif /* #ifndef _INV_MPU_H_ */

View File

@@ -1,126 +0,0 @@
/* ------------------------------------------
* Copyright (c) 2018, 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.
*
--------------------------------------------- */
/*
$License:
Copyright (C) 2011-2012 InvenSense Corporation, All Rights Reserved.
See included License.txt for License information.
$
*/
/**
* @addtogroup DRIVERS Sensor Driver Layer
* @brief Hardware drivers to communicate with sensors via I2C.
*
* @{
* @file inv_mpu_dmp_motion_driver.h
* @brief DMP image and interface functions.
* @details All functions are preceded by the dmp_ prefix to
* differentiate among MPL and general driver function calls.
*/
#ifndef _INV_MPU_DMP_MOTION_DRIVER_H_
#define _INV_MPU_DMP_MOTION_DRIVER_H_
#define TAP_X (0x01)
#define TAP_Y (0x02)
#define TAP_Z (0x04)
#define TAP_XYZ (0x07)
#define TAP_X_UP (0x01)
#define TAP_X_DOWN (0x02)
#define TAP_Y_UP (0x03)
#define TAP_Y_DOWN (0x04)
#define TAP_Z_UP (0x05)
#define TAP_Z_DOWN (0x06)
#define ANDROID_ORIENT_PORTRAIT (0x00)
#define ANDROID_ORIENT_LANDSCAPE (0x01)
#define ANDROID_ORIENT_REVERSE_PORTRAIT (0x02)
#define ANDROID_ORIENT_REVERSE_LANDSCAPE (0x03)
#define DMP_INT_GESTURE (0x01)
#define DMP_INT_CONTINUOUS (0x02)
#define DMP_FEATURE_TAP (0x001)
#define DMP_FEATURE_ANDROID_ORIENT (0x002)
#define DMP_FEATURE_LP_QUAT (0x004)
#define DMP_FEATURE_PEDOMETER (0x008)
#define DMP_FEATURE_6X_LP_QUAT (0x010)
#define DMP_FEATURE_GYRO_CAL (0x020)
#define DMP_FEATURE_SEND_RAW_ACCEL (0x040)
#define DMP_FEATURE_SEND_RAW_GYRO (0x080)
#define DMP_FEATURE_SEND_CAL_GYRO (0x100)
#define INV_WXYZ_QUAT (0x100)
/* Set up functions. */
int dmp_load_motion_driver_firmware(void);
int dmp_set_fifo_rate(unsigned short rate);
int dmp_get_fifo_rate(unsigned short *rate);
int dmp_enable_feature(unsigned short mask);
int dmp_get_enabled_features(unsigned short *mask);
int dmp_set_interrupt_mode(unsigned char mode);
int dmp_set_orientation(unsigned short orient);
int dmp_set_gyro_bias(long *bias);
int dmp_set_accel_bias(long *bias);
/* Tap functions. */
int dmp_register_tap_cb(void (*func)(unsigned char, unsigned char));
int dmp_set_tap_thresh(unsigned char axis, unsigned short thresh);
int dmp_set_tap_axes(unsigned char axis);
int dmp_set_tap_count(unsigned char min_taps);
int dmp_set_tap_time(unsigned short time);
int dmp_set_tap_time_multi(unsigned short time);
int dmp_set_shake_reject_thresh(long sf, unsigned short thresh);
int dmp_set_shake_reject_time(unsigned short time);
int dmp_set_shake_reject_timeout(unsigned short time);
/* Android orientation functions. */
int dmp_register_android_orient_cb(void (*func)(unsigned char));
/* LP quaternion functions. */
int dmp_enable_lp_quat(unsigned char enable);
int dmp_enable_6x_lp_quat(unsigned char enable);
/* Pedometer functions. */
int dmp_get_pedometer_step_count(unsigned long *count);
int dmp_set_pedometer_step_count(unsigned long count);
int dmp_get_pedometer_walk_time(unsigned long *time);
int dmp_set_pedometer_walk_time(unsigned long time);
/* DMP gyro calibration functions. */
int dmp_enable_gyro_cal(unsigned char enable);
/* Read function. This function should be called whenever the MPU interrupt is
* detected.
*/
int dmp_read_fifo(short *gyro, short *accel, long *quat,
unsigned long *timestamp, short *sensors, unsigned char *more);
#endif /* #ifndef _INV_MPU_DMP_MOTION_DRIVER_H_ */

View File

@@ -1,473 +0,0 @@
/* ------------------------------------------
* Copyright (c) 2018, 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.
*
--------------------------------------------- */
#include "arc/arc.h"
#include "arc/arc_builtin.h"
#include "embARC_toolchain.h"
#include "embARC_error.h"
#include "embARC_debug.h"
#include "device/ip_hal/dev_iic.h"
#include "mpu9250.h"
#include "board.h"
#include "inv_mpu.h"
#include "inv_mpu_dmp_motion_driver.h"
#include <math.h>
#define DEFAULT_MPU_HZ 200
// ****************************************
#define SMPLRT_DIV 0x19
#define CONFIG 0x1A
#define GYRO_CONFIG 0x1B
#define ACCEL_CONFIG 0x1C
#define ACCEL_CONFIG_2 0x1D
#define INT_PIN_CFG 0x37
#define INT_ENABLE 0x38
#define USER_CTRL 0x6A
#define PWR_MGMT_1 0x6B
#define PWR_MGMT_2 0x6C
#define MAG_CTRL 0x0A
#define MPU_WIM 0x75
#define MPU_ID 0x71
#define MAG_WIM 0x00
#define MAG_ID 0x48
#define ACCEL_XOUT_H 0x3B
#define GYRO_XOUT_H 0x43
#define MAG_XOUT_L 0x03
#ifdef MPU9250_USE_DMP
MPU9250_DEF_PTR mpu9250_ptr;
static signed char gyro_orientation[9] = { 1, 0, 0,
0, 1, 0,
0, 0, 1 };
static inline unsigned short inv_row_2_scale(const signed char *row)
{
unsigned short b;
if (row[0] > 0) {
b = 0;
} else if (row[0] < 0) {
b = 4;
} else if (row[1] > 0) {
b = 1;
} else if (row[1] < 0) {
b = 5;
} else if (row[2] > 0) {
b = 2;
} else if (row[2] < 0) {
b = 6;
} else {
b = 7; // error
}
return b;
}
static inline unsigned short inv_orientation_matrix_to_scalar(const signed char *mtx)
{
unsigned short scalar;
/*
XYZ 010_001_000 Identity Matrix
XZY 001_010_000
YXZ 010_000_001
YZX 000_010_001
ZXY 001_000_010
ZYX 000_001_010
*/
scalar = inv_row_2_scale(mtx);
scalar |= inv_row_2_scale(mtx + 3) << 3;
scalar |= inv_row_2_scale(mtx + 6) << 6;
return scalar;
}
static inline void run_self_test(void)
{
int result;
long gyro[3], accel[3];
unsigned char i = 0;
result = mpu_run_6500_self_test(gyro, accel, 1);
EMBARC_PRINTF("mpu run self test, result = %d\r\n");
if (result == 0x7) {
for (i = 0; i < 3; i++) {
gyro[i] = (long)(gyro[i] * 32.8f); // convert to +-1000dps
accel[i] *= 2048.f; // convert to +-16G
accel[i] = accel[i] >> 16;
gyro[i] = (long)(gyro[i] >> 16);
}
mpu_set_gyro_bias_reg(gyro);
mpu_set_accel_bias_6500_reg(accel);
}
}
#endif
#define MPU9250_CHECK_EXP_NORTN(EXPR) CHECK_EXP_NOERCD(EXPR, error_exit)
static int32_t _mpu_reg_write(MPU9250_DEF_PTR obj, uint32_t slaveaddr, uint8_t regaddr, uint8_t *val, uint8_t len)
{
int32_t ercd = E_PAR;
uint8_t data[1];
DEV_IIC_PTR iic_obj = iic_get_dev(obj->i2c_id);
dbg_printf(DBG_LESS_INFO, "[%s]%d: obj 0x%x, regaddr 0x%x, val 0x%x\r\n", __FUNCTION__, __LINE__, obj, regaddr, *val);
dbg_printf(DBG_MORE_INFO, "[%s]%d: iic_obj 0x%x -> 0x%x\r\n", __FUNCTION__, __LINE__, iic_obj, *iic_obj);
MPU9250_CHECK_EXP_NORTN(iic_obj != NULL);
data[0] = (uint8_t)(regaddr & 0xff);
iic_obj->iic_control(IIC_CMD_MST_SET_TAR_ADDR, CONV2VOID(slaveaddr));
ercd = iic_obj->iic_control(IIC_CMD_MST_SET_NEXT_COND, CONV2VOID(IIC_MODE_RESTART));
ercd = iic_obj->iic_write(data, 1);
ercd = iic_obj->iic_control(IIC_CMD_MST_SET_NEXT_COND, CONV2VOID(IIC_MODE_STOP));
ercd = iic_obj->iic_write(val, len);
error_exit:
return ercd;
}
static int32_t _mpu_reg_read(MPU9250_DEF_PTR obj, uint32_t slaveaddr, uint8_t regaddr, uint8_t *val, uint8_t len)
{
int32_t ercd = E_PAR;
uint8_t data[1];
DEV_IIC_PTR iic_obj = iic_get_dev(obj->i2c_id);
dbg_printf(DBG_MORE_INFO, "[%s]%d: iic_obj 0x%x -> 0x%x\r\n", __FUNCTION__, __LINE__, iic_obj, *iic_obj);
MPU9250_CHECK_EXP_NORTN(iic_obj != NULL);
data[0] = (uint8_t)(regaddr & 0xff);
iic_obj->iic_control(IIC_CMD_MST_SET_TAR_ADDR, CONV2VOID(slaveaddr));
ercd = iic_obj->iic_control(IIC_CMD_MST_SET_NEXT_COND, CONV2VOID(IIC_MODE_RESTART));
ercd = iic_obj->iic_write(data, 1);
ercd = iic_obj->iic_control(IIC_CMD_MST_SET_NEXT_COND, CONV2VOID(IIC_MODE_STOP));
ercd = iic_obj->iic_read(val, len);
error_exit:
return ercd;
}
int32_t mpu9250_sensor_init(MPU9250_DEF_PTR obj)
{
int32_t ercd = E_OK;
DEV_IIC_PTR iic_obj = iic_get_dev(obj->i2c_id);
dbg_printf(DBG_MORE_INFO, "[%s]%d: iic_obj 0x%x -> 0x%x\r\n", __FUNCTION__, __LINE__, iic_obj, *iic_obj);
MPU9250_CHECK_EXP_NORTN(iic_obj != NULL);
ercd = iic_obj->iic_open(DEV_MASTER_MODE, IIC_SPEED_STANDARD);
if ((ercd == E_OK) || (ercd == E_OPNED)) {
#ifndef MPU9250_USE_DMP
uint8_t config;
uint8_t data[0];
config = 0x80;
ercd = _mpu_reg_write(obj, obj->mpu_slvaddr, PWR_MGMT_1, &config, 1);// 0x6B
board_delay_ms(100);
/*
* get stable time source; Auto select clock source to be PLL gyroscope reference if ready
* else use the internal oscillator
*/
config = 0x01;
ercd = _mpu_reg_write(obj, obj->mpu_slvaddr, PWR_MGMT_1, &config, 1);
config = 0x00;
ercd = _mpu_reg_write(obj, obj->mpu_slvaddr, PWR_MGMT_2, &config, 1);
/* no i2c master */
ercd = _mpu_reg_write(obj, obj->mpu_slvaddr, USER_CTRL, &config, 1);
board_delay_ms(200);
ercd = _mpu_reg_read(obj, obj->mpu_slvaddr, MPU_WIM, data, 1);
if (data[0] != MPU_ID) {
dbg_printf(DBG_MORE_INFO, "mpu init failed\r\n");
return E_SYS;
}
config = 0x07; // SAMPLE_RATE=Internal_Sample_Rate(1khz) / (1 + SMPLRT_DIV)
ercd = _mpu_reg_write(obj, obj->mpu_slvaddr, SMPLRT_DIV, &config, 1); // Sample Rate Divider
config = 0x06;
ercd = _mpu_reg_write(obj, obj->mpu_slvaddr, CONFIG, &config, 1);// DLPF config: 5Hz
config = 0x18;
ercd = _mpu_reg_write(obj, obj->mpu_slvaddr, GYRO_CONFIG, &config, 1);// +2000dps
config = 0x00;
ercd = _mpu_reg_write(obj, obj->mpu_slvaddr, ACCEL_CONFIG, &config, 1);// +-2g
config = 0x08;
ercd = _mpu_reg_write(obj, obj->mpu_slvaddr, ACCEL_CONFIG_2, &config, 1); // 1.13kHz
config = 0x2; // set passby
ercd = _mpu_reg_write(obj, obj->mpu_slvaddr, INT_PIN_CFG, &config, 1);
board_delay_ms(100);
ercd = _mpu_reg_read(obj, obj->mag_slvaddr, MAG_WIM, data, 1);// read mag who i am;
if (data[0] != MAG_ID) {
dbg_printf(DBG_MORE_INFO, "mpu init failed\r\n");
return E_SYS;
}
config = 0x01;
ercd = _mpu_reg_write(obj, obj->mag_slvaddr, MAG_CTRL, &config, 1);// mag single measurement mode
#else
mpu9250_ptr = obj;
if (!mpu_init()) {
if (!mpu_set_sensors(INV_XYZ_GYRO | INV_XYZ_ACCEL)) {
EMBARC_PRINTF("mpu_set_sensor complete ......\r\n");
}
mpu_delay_ms(50);
if (!mpu_configure_fifo(INV_XYZ_GYRO | INV_XYZ_ACCEL)) {
EMBARC_PRINTF("mpu_configure_fifo complete ......\r\n");
}
mpu_delay_ms(50);
if (!mpu_set_sample_rate(DEFAULT_MPU_HZ)) {
EMBARC_PRINTF("mpu_set_sample_rate complete ......\r\n");
}
mpu_delay_ms(50);
// if(!mpu_set_gyro_bias_reg(gyroZero))
// EMBARC_PRINTF("mpu_set_gyro_bias_reg complete ......\r\n");
mpu_delay_ms(50);
if (!dmp_load_motion_driver_firmware()) {
EMBARC_PRINTF("dmp_load_motion_driver_firmware complete ......\r\n");
}
mpu_delay_ms(50);
if (!dmp_set_orientation(inv_orientation_matrix_to_scalar(gyro_orientation))) {
EMBARC_PRINTF("dmp_set_orientation complete ......\r\n");
}
mpu_delay_ms(50);
if (!dmp_enable_feature(DMP_FEATURE_6X_LP_QUAT | DMP_FEATURE_SEND_RAW_ACCEL |
DMP_FEATURE_SEND_RAW_GYRO)) {
// DMP_FEATURE_SEND_CAL_GYRO | DMP_FEATURE_GYRO_CAL))
EMBARC_PRINTF("dmp_enable_feature complete ......\r\n");
}
mpu_delay_ms(50);
if (!dmp_set_fifo_rate(DEFAULT_MPU_HZ)) {
EMBARC_PRINTF("dmp_set_fifo_rate complete ......\r\n");
}
mpu_delay_ms(50);
// run_self_test();
mpu_delay_ms(50);
if (!mpu_set_dmp_state(1)) {
EMBARC_PRINTF("mpu_set_dmp_state complete ......\r\n");
}
mpu_delay_ms(50);
}
#endif
}
error_exit:
return ercd;
}
int32_t mpu9250_sensor_deinit(MPU9250_DEF_PTR obj)
{
int32_t ercd = E_OK;
DEV_IIC_PTR iic_obj = iic_get_dev(obj->i2c_id);
ercd = iic_obj->iic_close();
MPU9250_CHECK_EXP_NORTN(ercd == E_OK);
error_exit:
return ercd;
}
int32_t mpu9250_sensor_read(MPU9250_DEF_PTR obj, MPU9250_DATA_PTR mp_data)
{
int32_t ercd = E_OK;
MPU9250_CHECK_EXP_NORTN(mp_data != NULL);
#ifndef MPU9250_USE_DMP
uint8_t data[6];
uint8_t config;
ercd = _mpu_reg_read(obj, obj->mpu_slvaddr, GYRO_XOUT_H, data, 6);
if (ercd != 6) {
ercd = E_OBJ;
goto error_exit;
} else {
ercd = E_OK;
mp_data->gyro_x = ((int16_t)data[0] << 8) + ((int16_t)data[1]);
mp_data->gyro_y = ((int16_t)data[2] << 8) + ((int16_t)data[3]);
mp_data->gyro_z = ((int16_t)data[4] << 8) + ((int16_t)data[5]);
}
ercd = _mpu_reg_read(obj, obj->mpu_slvaddr, ACCEL_XOUT_H, data, 6);
if (ercd != 6) {
ercd = E_OBJ;
goto error_exit;
} else {
ercd = E_OK;
mp_data->accel_x = ((int16_t)data[0] << 8) + ((int16_t)data[1]);
mp_data->accel_y = ((int16_t)data[2] << 8) + ((int16_t)data[3]);
mp_data->accel_z = ((int16_t)data[4] << 8) + ((int16_t)data[5]);
}
ercd = _mpu_reg_read(obj, obj->mag_slvaddr, MAG_XOUT_L, data, 6);
if (ercd != 6) {
ercd = E_OBJ;
} else {
ercd = E_OK;
mp_data->mag_x = ((int16_t)data[1] << 8) + ((int16_t)data[0]);
mp_data->mag_y = ((int16_t)data[3] << 8) + ((int16_t)data[2]);
mp_data->mag_z = ((int16_t)data[5] << 8) + ((int16_t)data[4]);
}
config = 0x01;
ercd = _mpu_reg_write(obj, obj->mag_slvaddr, MAG_CTRL, &config, 1);// mag single measurement mode
#else
short gyro[3], accel[3], sensors;
float q0 = 1.0f, q1 = 0.0f, q2 = 0.0f, q3 = 0.0f;
unsigned long sensor_timestamp;
unsigned char more;
long quat[4];
float q30 = (float)(1 << 30);
if (dmp_read_fifo(gyro, accel, quat, &sensor_timestamp, &sensors, &more) == 0) {
mp_data->gyro_x = gyro[0];
mp_data->gyro_y = gyro[1];
mp_data->gyro_z = gyro[2];
mp_data->accel_x = accel[0];
mp_data->accel_y = accel[1];
mp_data->accel_z = accel[2];
if (sensors & INV_WXYZ_QUAT) {
q0 = quat[0] / q30;
q1 = quat[1] / q30;
q2 = quat[2] / q30;
q3 = quat[3] / q30;
mp_data->pitch = (float)asin(-2 * q1 * q3 + 2 * q0 * q2) * 57.3f;
mp_data->roll = (float)atan2(2 * q2 * q3 + 2 * q0 * q1, -2 * q1 * q1 - 2 * q2 * q2 + 1) * 57.3f;
mp_data->yaw = (float)atan2(2 * (q1 * q2 + q0 * q3), q0 * q0 + q1 * q1 - q2 * q2 - q3 * q3) * 57.3f;
return 0;
}
}
#endif
error_exit:
return ercd;
}
#ifdef MPU9250_USE_DMP
int32_t mpu_iic_write(uint32_t slaveaddr, uint8_t regaddr, uint8_t len, uint8_t *val)
{
int32_t ercd = E_PAR;
uint8_t data[1];
DEV_IIC_PTR iic_obj = iic_get_dev(mpu9250_ptr->i2c_id);
dbg_printf(DBG_LESS_INFO, "[%s]%d: obj 0x%x, regaddr 0x%x, val 0x%x\r\n", __FUNCTION__, __LINE__, obj, regaddr, *val);
dbg_printf(DBG_MORE_INFO, "[%s]%d: iic_obj 0x%x -> 0x%x\r\n", __FUNCTION__, __LINE__, iic_obj, *iic_obj);
MPU9250_CHECK_EXP_NORTN(iic_obj != NULL);
data[0] = (uint8_t)(regaddr & 0xff);
iic_obj->iic_control(IIC_CMD_MST_SET_TAR_ADDR, CONV2VOID(slaveaddr));
ercd = iic_obj->iic_control(IIC_CMD_MST_SET_NEXT_COND, CONV2VOID(IIC_MODE_RESTART));
ercd = iic_obj->iic_write(data, 1);
ercd = iic_obj->iic_control(IIC_CMD_MST_SET_NEXT_COND, CONV2VOID(IIC_MODE_STOP));
ercd = iic_obj->iic_write(val, len);
if (ercd == len) {
ercd = E_OK;
}
error_exit:
return ercd;
}
int32_t mpu_iic_read(uint32_t slaveaddr, uint8_t regaddr, uint8_t len, uint8_t *val)
{
int32_t ercd = E_PAR;
uint8_t data[1];
DEV_IIC_PTR iic_obj = iic_get_dev(mpu9250_ptr->i2c_id);
dbg_printf(DBG_MORE_INFO, "[%s]%d: iic_obj 0x%x -> 0x%x\r\n", __FUNCTION__, __LINE__, iic_obj, *iic_obj);
MPU9250_CHECK_EXP_NORTN(iic_obj != NULL);
data[0] = (uint8_t)(regaddr & 0xff);
iic_obj->iic_control(IIC_CMD_MST_SET_TAR_ADDR, CONV2VOID(slaveaddr));
ercd = iic_obj->iic_control(IIC_CMD_MST_SET_NEXT_COND, CONV2VOID(IIC_MODE_RESTART));
ercd = iic_obj->iic_write(data, 1);
ercd = iic_obj->iic_control(IIC_CMD_MST_SET_NEXT_COND, CONV2VOID(IIC_MODE_STOP));
ercd = iic_obj->iic_read(val, len);
if (ercd == len) {
ercd = E_OK;
}
error_exit:
return ercd;
}
int mpu_get_ms(unsigned long *count)
{
*count = (unsigned long)OSP_GET_CUR_MS();
return 0;
}
void mpu_delay_ms(uint32_t ms)
{
board_delay_ms(ms);
}
#endif

View File

@@ -1,87 +0,0 @@
/* ------------------------------------------
* Copyright (c) 2018, Synopsys, Inc. All rights reserved.
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
* 1) Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2) Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
* 3) Neither the name of the Synopsys, Inc., nor the names of its contributors may
* be used to endorse or promote products derived from this software without
* specific prior written permission.
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
--------------------------------------------- */
#ifndef H_MPU9250
#define H_MPU9250
// MPU9250 (Nine-Axis (Gyro + Accelerometer + Compass) sensor using I2C bus) is on IOTDK board
#include "device/ip_hal/dev_iic.h"
#define MPU9250_USE_DMP
#define MPU9250_AD0_PIN 0 /*!< I2C Serial Bus Address Selection Pin */
#define MPU9250_IIC_ADDRESS (0x68 + (MPU9250_AD0_PIN << 1))
#define MAG_IIC_ADDRESS 0x0C
#ifdef __cplusplus
extern "C" {
#endif
typedef struct {
int16_t accel_x;
int16_t accel_y;
int16_t accel_z;
int16_t gyro_x;
int16_t gyro_y;
int16_t gyro_z;
int16_t mag_x;
int16_t mag_y;
int16_t mag_z;
float pitch;
float roll;
float yaw;
} MPU9250_DATA, *MPU9250_DATA_PTR;
typedef struct {
uint32_t i2c_id;
uint32_t mpu_slvaddr;
uint32_t mag_slvaddr;
} MPU9250_DEF, *MPU9250_DEF_PTR;
#define MPU9250_DEFINE(NAME, I2C_ID, SLAVE_ADDRESS) \
MPU9250_DEF __ ## NAME = { \
.i2c_id = I2C_ID, \
.mpu_slvaddr = SLAVE_ADDRESS, \
.mag_slvaddr = MAG_IIC_ADDRESS \
}; \
MPU9250_DEF_PTR NAME = &__ ## NAME
extern int32_t mpu9250_sensor_init(MPU9250_DEF_PTR obj);
extern int32_t mpu9250_sensor_deinit(MPU9250_DEF_PTR obj);
extern int32_t mpu9250_sensor_read(MPU9250_DEF_PTR obj, MPU9250_DATA_PTR mp_data);
extern int32_t mpu_iic_read(uint32_t slaveaddr, uint8_t regaddr, uint8_t len, uint8_t *val);
extern int32_t mpu_iic_write(uint32_t slaveaddr, uint8_t regaddr, uint8_t len, uint8_t *val);
int mpu_get_ms(unsigned long *count);
void mpu_delay_ms(uint32_t ms);
#ifdef __cplusplus
}
#endif
#endif /* H_MPU9250 */

View File

@@ -1,2 +0,0 @@
DEV_CSRCDIR += $(EMBARC_ROOT)/device/peripheral/sensor/imu/mpu9250
DEV_INCDIR += $(EMBARC_ROOT)/device/peripheral/sensor/imu/mpu9250

View File

@@ -1,490 +0,0 @@
/* ------------------------------------------
* 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.
*
--------------------------------------------- */
/**
* @file
* @ingroup ARC_HAL_CORE_COMM
* @brief Header file for common core definitions
*/
/**
* @addtogroup ARC_HAL_CORE_COMM
* @{
*/
#ifndef H_ARC_CORE
#define H_ARC_CORE
#include "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_VEC_UNIT (14) /*!< vector unit exception (Vector stack pointer check violation is detected in the vector unit.) */
#define EXC_NO_RESERVE0 (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_VEC_UNIT (0x38) /*!< EXC_NO_VEC_UNIT offset */
#define EXC_VECTOR_RESERVE0 (0x3c) /*!< EXC_NO_RESERVE0 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)
#define AUX_SEC_STAT_BIT_ERM (31)
/**
* @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 */
#define AUX_STATUS_BIT_HALT (0) /*!< halt bit */
#define AUX_STATUS_BIT_SC (14) /*!< stack check bit */
#define AUX_STATUS_BIT_AD (19) /*!< alignment check bit */
#define AUX_STATUS_BIT_US (20) /*!< user sleep mode enable bit */
#define AUX_STATUS_RB(x) ((x) << 16) /*!< register bank */
/* masks correspond to STATUS32 bit-field */
#define AUX_STATUS_MASK_AE (1 << AUX_STATUS_BIT_AE) /*!< mask of AUX_STATUS_BIT_AE */
#define AUX_STATUS_MASK_DE (1 << AUX_STATUS_BIT_DE) /*!< mask of AUX_STATUS_BIT_DE */
#define AUX_STATUS_MASK_U (1 << AUX_STATUS_BIT_U) /*!< mask of AUX_STATUS_BIT_U */
#define AUX_STATUS_MASK_L (1 << AUX_STATUS_BIT_L) /*!< mask of AUX_STATUS_BIT_L */
#define AUX_STATUS_MASK_IE (1 << AUX_STATUS_BIT_IE) /*!< mask of AUX_STATUS_BIT_IE */
#define AUX_STATUS_MASK_HALT (1 << AUX_STATUS_BIT_HALT) /*!< mask of AUX_STATUS_BIT_HALT */
#define AUX_STATUS_MASK_SC (1 << AUX_STATUS_BIT_SC) /*!< mask of AUX_STATUS_BIT_SC */
#define AUX_STATUS_MASK_AD (1 << AUX_STATUS_BIT_AD) /*!< mask of AUX_STATUS_BIT_AD */
#define AUX_STATUS_MASK_US (1 << AUX_STATUS_BIT_US) /*!< mask of AUX_STATUS_BIT_US */
#ifdef ARC_FEATURE_UNALIGNED
#define STATUS32_RESET_VALUE (AUX_STATUS_MASK_AD | AUX_STATUS_MASK_US)
#else
#define STATUS32_RESET_VALUE (AUX_STATUS_MASK_US)
#endif
/** @} */
/**
* @name zero overhead loop auxiliary register
* @{
*/
#define AUX_LP_START (0x2) /*!< loop start address (32-bit) */
#define AUX_LP_END (0x3) /*!< loop end address (32-bit) */
/** @} */
#define AUX_USER_SP (0xd) /*!< user-mode stack pointer */
/* added in secure mode */
#define AUX_KERNEL_SP (0x38) /*!< kernel-mode stack pointer */
#define AUX_SEC_U_SP (0x39) /*!< secure user-mode stack pointer */
#define AUX_SEC_K_SP (0x3a) /*!< secure kernel-mode stack pointer */
/* additional stack checking registers for secure mode */
#define AUX_S_USTACK_BASE (0x263)
#define AUX_S_USTACK_TOP (0x262)
#define AUX_S_KSTACK_BASE (0x267)
#define AUX_S_KSTACK_TOP (0x266)
#define AUX_KSTACK_TOP (0x264)
#define AUX_KSTACK_BASE (0x265)
#define AUX_USTACK_TOP (0x260)
#define AUX_USTACK_BASE (0x261)
/**
* @name auxiliary register for hardware counter 0 and 1
* @{
*/
#define AUX_TIMER0_LIMIT (0x23) /*!< timer 0 limit value */
#define AUX_TIMER0_CTRL (0x22) /*!< timer 0 control value */
#define AUX_TIMER0_CNT (0x21) /*!< timer 0 count value */
#define AUX_TIMER1_LIMIT (0x102) /*!< timer 1 limit value */
#define AUX_TIMER1_CTRL (0x101) /*!< timer 1 control value */
#define AUX_TIMER1_CNT (0x100) /*!< timer 1 count value */
/** @} */
#define AUX_SECURE_TIMER0_CNT (0x106) /*!< secure timer 0 count value */
#define AUX_SECURE_TIMER0_CTRL (0x107) /*!< secure timer 0 control value */
#define AUX_SECURE_TIMER0_LIMIT (0x108) /*!< secure timer 0 limit value */
#define AUX_SECURE_TIMER1_CNT (0x109) /*!< secure timer 1 count value */
#define AUX_SECURE_TIMER1_CTRL (0x10a) /*!< secure timer 1 control value */
#define AUX_SECURE_TIMER1_LIMIT (0x10b) /*!< secure timer 1 limit value */
/**
* @name auxiliary register for real-time counter
* @{
*/
#define AUX_RTC_CTRL (0x103) /*!< real-time counter control register */
#define AUX_RTC_LOW (0x104) /*!< real-time counter count low register */
#define AUX_RTC_HIGH (0x105) /*!< real-time counter count high register */
/** @} */
/**
* @name indexed table auxiliary register
* @{
*/
#define AUX_JLI_BASE (0x290) /*!< jump and link indexed base address */
#define AUX_LDI_BASE (0x291) /*!< load indexed base address */
#define AUX_EI_BASE (0x292) /*!< execute indexed base address */
/** @} */
/**
* @name baseline auxiliary register set
* @{
*/
/* exception related aux regs */
#define AUX_ERRET (0x400) /*!< exception return address */
#define AUX_ERBTA (0x401) /*!< BTA saved on exception entry */
#define AUX_ERSTATUS (0x402) /*!< STATUS32 saved on exception */
#define AUX_ECR (0x403) /*!< exception cause register */
#define AUX_EFA (0x404) /*!< exception fault address */
#define AUX_BTA (0x412) /*!< branch target address */
/** @} */
/* New register to control which exceptions can be handled in NS mode */
#define AUX_ERSEC_STAT (0x406)
#define AUX_ERSEC_STAT_BIT_ERM (31)
#define AUX_SEC_EXCEPT (0x407)
/**
* @name MPU register set
* @{
*/
#define AUX_MPU_EN (0x409) /*!< MPU enable register */
#define AUX_MPU_ECR (0x420) /*!< MPU exception cause */
#define AUX_MPU_RDB0 (0x422) /*!< MPU region descriptor base 0 */
#define AUX_MPU_RDP0 (0x423) /*!< MPU region descriptor permission 0 */
/* MPU register set in silverstone */
#define AUX_MPU_INDEX (0x448)
#define AUX_MPU_INDEX_BIT_D (31)
#define AUX_MPU_RSTART (0x449)
#define AUX_MPU_REND (0x44a)
#define AUX_MPU_RPER (0x44b)
#define AUX_MPU_RPER_BIT_S (15)
#define AUX_MPU_PROBE (0x44c)
#define AUX_NSC_TABLE_BASE (0x269)
#define AUX_NSC_TABLE_TOP (0x268)
/** @} */
/**
* @name exception cause register (ECR) bit-field definition
* @{
*/
#define AUX_ECR_VEC_MASK (0xff0000) /*!< [23:16] = exception vector */
#define AUX_ECR_CODE_MASK (0x00ff00) /*!< [15: 8] = exception cause code */
#define AUX_ECR_PARAM_MASK (0x0000ff) /*!< [ 7: 0] = exception parameters */
/** @} */
/**
* @name exception vector number and cause code
* @{
*/
#define AUX_ECR_V_INSN_ERR (0x02) /*!< vector number of illegal instruction */
#define AUX_ECR_V_MACH_CHK (0x03) /*!< vector number of machine check */
#define AUX_ECR_V_ITLB_MISS (0x04) /*!< vector number of instruction TLB missing exception */
#define AUX_ECR_V_DTLB_MISS (0x05) /*!< vector number of data TLB missing exception */
#define AUX_ECR_V_PROTV (0x06) /*!< vector number of protection violation */
#define AUX_ECR_V_PRIV (0x07) /*!< vector number of privilege violation */
#define AUX_ECR_V_SWI (0x08) /*!< vector number of software interrupt */
#define AUX_ECR_V_TRAP (0x09) /*!< vector number of trap */
#define AUX_ECR_V_EXT (0x0a) /*!< vector number of extension */
#define AUX_ECR_V_DIV_ZERO (0x0b) /*!< vector number of divide by zero*/
#define AUX_ECR_V_DC_ERR (0x0c) /*!< vector number of data cache consistency error */
#define AUX_ECR_V_MISALIG_DATA (0x0d) /*!< vector number of misaligned data access */
#define AUX_ECR_C_PROTV_INST_FETCH (0x00) /*!< cause code of instruction fetch (protection violation) */
#define AUX_ECR_C_PROTV_LOAD (0x01) /*!< cause code of memory read related (protection violation) */
#define AUX_ECR_C_PROTV_STORE (0x02) /*!< cause code of memory write related (protection violation) */
#define AUX_ECR_C_PROTV_XCHG (0x03) /*!< cause code of read-modify-write related (protection violation) */
#define AUX_ECR_C_PROTV_NS_VECT_IN_S (0x10) /*!< cause code of NS vector table in S memory (protection violation) */
#define AUX_ECR_C_PROTV_NS_HANDLER_IN_S (0x11) /*!< cause code of NS handler in S memory (protection violation) */
#define AUX_ECR_C_PROTV_NSC_RANGE (0x12) /*!< cause code of NSC table range violation (protection violation) */
#define AUX_ECR_C_PRIV_PRIV (0x00) /*!< cause code of privilege violation (privilege violation) */
#define AUX_ECR_C_PRIV_DIS_EXT (0x01) /*!< cause code of disabled extension (privilege violation) */
#define AUX_ECR_C_PRIV_ACT_HIT (0x02) /*!< cause code of action point hit (privilege violation) */
#define AUX_ECR_C_PRIV_ACT_SECURE (0x10) /*!< cause code of secure related operation (privilege violation) */
#define AUX_ECR_C_MCHK_DUP_TLB (0x01) /*!< @todo definition is to be added. */
#define AUX_ECR_C_BIT_DTLB_LD_MISS (8) /*!< @todo definition is to be added. */
#define AUX_ECR_C_BIT_DTLB_ST_MISS (9) /*!< @todo definition is to be added. */
/** @} */
/**
* @name interrupt related auxiliary register
* @{
*/
#define AUX_IRQ_CTRL (0xe) /*!< interrupt context saving control register */
#define AUX_INT_VECT_BASE (0x25) /*!< interrupt vector base register */
#define AUX_INT_VECT_BASE_S (0x26) /*!< secure interrupt vector based register */
#define AUX_IRQ_ACT (0x43) /*!< active interrupts register */
#define AUX_IRQ_CAUSE (0x40a) /*!< interrupt cause register */
#define AUX_IRQ_SELECT (0x40b) /*!< interrupt select register */
#define AUX_IRQ_PRIORITY (0x206) /*!< interrupt priority register */
#define AUX_IRQ_PRIORITY_BIT_S (0x8) /*!< S bit offset in interrupt priority register */
#define AUX_IRQ_ENABLE (0x40c) /*!< interrupt enable register */
#define AUX_IRQ_TRIGGER (0x40d) /*!< interrupt trigger: level or pulse */
#define AUX_IRQ_PENDING (0x416) /*!< interrupt pending register */
#define AUX_IRQ_PLUSE_CLR (0x415) /*!< interrupt pulse cancel register */
#define AUX_IRQ_STATUS (0x40f) /*!< interrupt status register */
#define AUX_IRQ_PRI_PENDING (0x200) /*!< interrupt priority pending register */
#define AUX_IRQ_HINT (0x201) /*!< software interrupt trigger */
/** @} */
/**
* @name cache related auxiliary register
* @{
*/
#define AUX_IC_IVIC (0x10) /*!< invalidate instruction cache */
#define AUX_IC_CTRL (0x11) /*!< instruction cache control register */
#define AUX_IC_LIL (0x13) /*!< lock instruction cache line */
#define AUX_IC_IVIL (0x19) /*!< invalidate instruction cache line */
#define AUX_IC_RAM_ADDR (0x1a) /*!< instruction cache external access address */
#define AUX_IC_TAG (0x1b) /*!< instruction cache tag access */
#define AUX_IC_XTAG (0x1c) /*!< instruction cache secure bit tag */
#define AUX_IC_DATA (0x1d) /*!< instruction cache data access */
#define AUX_DC_IVDC (0x47) /*!< invalidate data cache */
#define AUX_DC_CTRL (0x48) /*!< data cache control register */
#define AUX_DC_LDL (0x49) /*!< lock data cache line */
#define AUX_DC_IVDL (0x4a) /*!< invalidate data cache line */
#define AUX_DC_FLSH (0x4b) /*!< flush data cache */
#define AUX_DC_FLDL (0x4c) /*!< flush data line */
#define AUX_DC_RAM_ADDR (0x58) /*!< data cache external access address */
#define AUX_DC_TAG (0x59) /*!< data cache tag access */
#define AUX_DC_XTAG (0x5a) /*!< data cache secure bit tag */
#define AUX_DC_DATA (0x5b) /*!< data cache data access */
/** @} */
/**
* @name dmac related auxiliary register
* @{
*/
#define AUX_DMACTRL (0x680) /*!< DMA control register */
#define AUX_DMACENB (0x681) /*!< DMA channel enable register */
#define AUX_DMACDSB (0x682) /*!< DMA channel disable register */
#define AUX_DMACHPRI (0x683) /*!< DMA channel high priority level register */
#define AUX_DMACNPRI (0x684) /*!< DMA channel normal priority level register */
#define AUX_DMACREQ (0x685) /*!< DMA channel transfer request register */
#define AUX_DMACSTAT0 (0x686) /*!< DMA channel status register 0 */
#define AUX_DMACSTAT1 (0x687) /*!< DMA channel status register 1 */
#define AUX_DMACIRQ (0x688) /*!< DMA channel interrupt request status/clear register */
#define AUX_DMACBASE (0x689) /*!< DMA channel structure register base address */
#define AUX_DMACRST (0x68A) /*!< DMA channel reset register base address */
#define AUX_DMACTRL0 (0x690) /*!< DMA channel 0 control register when mapped in aux */
#define AUX_DMASAR0 (0x691) /*!< DMA channel 0 source address register when mapped in aux */
#define AUX_DMADAR0 (0x692) /*!< DMA channel 0 destination register when mapped in aux */
#define AUX_DMACTRLx (AUX_DMACTRL0) /*!< DMA channel 0 control register when mapped in aux */
#define AUX_DMASARx (AUX_DMASAR0) /*!< DMA channel 0 source address register when mapped in aux */
#define AUX_DMADARx (AUX_DMADAR0) /*!< DMA channel 0 destination register when mapped in aux */
/** @} */
/**
* @name fpu related auxiliary register
* @{
*/
#define AUX_FPU_CTRL (0x300) /*!< FPU ctrl register */
#define AUX_FPU_STATUS (0x301) /*!< FPU status register */
#define AUX_FPU_DPFP1L (0x302) /*!< double float D1 register low */
#define AUX_FPU_DPFP1H (0x303) /*!< double float D1 register high */
#define AUX_FPU_DPFP2L (0x304) /*!< double float D2 register low */
#define AUX_FPU_DPFP2H (0x305) /*!< double float D2 register high */
/** @} */
/**
* @name dsp related auxiliary register
* @{
*/
#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)
/** @} */
/**
* @name other auxiliary register
* @{
*/
#define AUX_IDENTITY (0x4) /*!< identity register */
#define AUX_DMP_PERIPHERAL (0x20a) /*!< peripheral memory region */
#define AUX_XFLAGS (0x44f) /*!< user extension flags register */
#define AUX_CONNECT_CMD (0x600) /*!< ARConnect Command Register, CONNECT_CMD */
#define AUX_CONNECT_WDATA (0x601) /*!< ARConnect Write Data Register, CONNECT_WDATA */
#define AUX_CONNECT_READBACK (0x602) /*!< ARConnect Read Data Register, CONNECT_READBACK */
#define AUX_SMART_CONTROL (0x700) /*!< SmaRT Control Register, SMART_CONTROL */
#define AUX_SMART_DATA (0x701) /*!< SmaRT Data Register, SMART_DATA */
/** @} */
#ifndef __ASSEMBLY__
#ifdef __cplusplus
extern "C" {
#endif
#ifdef __cplusplus
}
#endif
#endif /* __ASSEMBLY__ */
#endif /* H_ARC_CORE */
/** @} */

View File

@@ -1,705 +0,0 @@
/* ------------------------------------------
* 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.
*
--------------------------------------------- */
/**
* @file
* @ingroup ARC_HAL_MISC
* @brief common macro definitions for assembly file
*/
/** @cond ARC_HAL_ASM_COMMON */
#ifndef H_ARC_ASM_COMMON
#define H_ARC_ASM_COMMON
#include "arc/arc.h"
#ifdef __ASSEMBLY__
/* the assembly macro definitions in ARC GNU and MWDT are
* different, so need different processing
*/
#if defined(__GNU__)
#define MACRO_ARG(x) \ x
#define ASM_MACRO1(name, arg1) name arg1
#define ASM_MACRO2(name, arg1, arg2) name arg1 arg2
#define ASM_MACRO3(name, arg1, arg2, arg3) name arg1 arg, agr3
#define ASM_MACRO4(name, arg1, arg2, arg3, arg4) name arg1 arg2 arg3 arg4
#else
#define MACRO_ARG(x) x
#define ASM_MACRO1(name, arg1) name, arg1
#define ASM_MACRO2(name, arg1, arg2) name, arg1, arg2
#define ASM_MACRO3(name, arg1, arg2, arg3) name, arg1, arg2, agr3
#define ASM_MACRO4(name, arg1, arg2, arg3, arg4) name, arg1, arg2, arg3, arg4
#endif
/* Note on the LD/ST addr modes with addr reg wback
*
* LD.a same as LD.aw
*
* LD.a reg1, [reg2, x] => Pre Incr
* Eff Addr for load = [reg2 + x]
*
* LD.ab reg1, [reg2, x] => Post Incr
* Eff Addr for load = [reg2]
*/
.macro ASM_MACRO1(PUSH, reg)
st.a MACRO_ARG(reg), [sp, -4]
.endm
.macro ASM_MACRO1(PUSHAX, aux)
lr r10, [MACRO_ARG(aux)]
PUSH r10
.endm
.macro ASM_MACRO1(POP, reg)
ld.ab MACRO_ARG(reg), [sp, 4]
.endm
.macro ASM_MACRO1(POPAX, aux)
POP r10
sr r10, [MACRO_ARG(aux)]
.endm
/* macro to get the cpu id */
.macro ASM_MACRO1(GET_CORE_ID, reg)
lr MACRO_ARG(reg), [AUX_IDENTITY]
xbfu MACRO_ARG(reg), MACRO_ARG(reg), 0xe8
.endm
/* macro to save accl regs */
.macro SAVE_R58_R59
#if ARC_FEATURE_FPU || ARC_FEATURE_DSP || ARC_FEATURE_MPU_OPTION_NUM > 6
PUSH r58
PUSH r59
#endif
.endm
/* macro to restore accl regs */
.macro RESTORE_R58_R59
#if ARC_FEATURE_FPU || ARC_FEATURE_DSP || ARC_FEATURE_MPU_OPTION_NUM > 6
POP r59
POP r58
#endif
.endm
/* macro to save fpu related regs */
.macro SAVE_FPU_REGS
#if ARC_FEATURE_FPU
PUSHAX AUX_FPU_CTRL
PUSHAX AUX_FPU_STATUS
#if ARC_FEATURE_FPU_DA
PUSHAX AUX_FPU_DPFP1L
PUSHAX AUX_FPU_DPFP1H
PUSHAX AUX_FPU_DPFP2L
PUSHAX AUX_FPU_DPFP2H
#endif
#endif
.endm
/* macro to restore fpu related regs */
.macro RESTORE_FPU_REGS
#if ARC_FEATURE_FPU
#if ARC_FEATURE_FPU_DA
POPAX AUX_FPU_DPFP2H
POPAX AUX_FPU_DPFP2L
POPAX AUX_FPU_DPFP1H
POPAX AUX_FPU_DPFP1L
#endif
POPAX AUX_FPU_STATUS
POPAX AUX_FPU_CTRL
#endif
.endm
/* macro to save dsp related regs */
.macro SAVE_DSP_REGS
#if ARC_FEATURE_DSP
PUSHAX AUX_DSP_CTRL
PUSHAX AUX_ACC0_LO
PUSHAX AUX_ACC0_GLO
PUSHAX AUX_ACC0_HI
PUSHAX AUX_ACC0_GHI
#if ARC_FEATURE_DSP_COMPLEX
PUSHAX AUX_DSP_BFLY0
PUSHAX AUX_DSP_FFT_CTRL
#endif
#endif
.endm
/* macro to restore dsp related regs */
.macro RESTORE_DSP_REGS
#if ARC_FEATURE_DSP
#if ARC_FEATURE_DSP_COMPLEX
POPAX AUX_DSP_FFT_CTRL
POPAX AUX_DSP_BFLY0
#endif
POPAX AUX_ACC0_GHI
POPAX AUX_ACC0_HI
POPAX AUX_ACC0_GLO
POPAX AUX_ACC0_LO
POPAX AUX_DSP_CTRL
#endif
.endm
/*--------------------------------------------------------------
* 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
#if defined(ARC_ENABLE_EXTRA_CALLEE)
#if ARC_FEATURE_SEC_PRESENT
PUSHAX AUX_KERNEL_SP
PUSHAX AUX_SEC_K_SP
#else
PUSHAX AUX_USER_SP
#endif
#endif
#if ARC_FEATURE_FPU_DSP_CONTEXT
SAVE_FPU_REGS
SAVE_DSP_REGS
#endif
.endm
.macro RESTORE_CALLEE_REGS
#if ARC_FEATURE_FPU_DSP_CONTEXT
RESTORE_DSP_REGS
RESTORE_FPU_REGS
#endif
#if defined(ARC_ENABLE_EXTRA_CALLEE)
#if ARC_FEATURE_SEC_PRESENT
POPAX AUX_SEC_K_SP
POPAX AUX_KERNEL_SP
#else
POPAX AUX_USER_SP
#endif
#endif
#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 to clear callee regs */
.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
#if ARC_FEATURE_FPU_DSP_CONTEXT
#if ARC_FEATURE_FPU
#if ARC_FEATURE_FPU_DA
sr 0, [AUX_FPU_DPFP2H]
sr 0, [AUX_FPU_DPFP2L]
sr 0, [AUX_FPU_DPFP1H]
sr 0, [AUX_FPU_DPFP1L]
#endif
sr 0, [AUX_FPU_STATUS]
sr 0, [AUX_FPU_CTRL]
#endif /* ARC_FEATURE_FPU */
#if ARC_FEATURE_DSP
#if ARC_FEATURE_DSP_COMPLEX
sr 0, [AUX_DSP_FFT_CTRL]
sr 0, [AUX_DSP_BFLY0]
#endif
sr 0, [AUX_ACC0_GHI]
sr 0, [AUX_ACC0_HI]
sr 0, [AUX_ACC0_GLO]
sr 0, [AUX_ACC0_LO]
sr 0, [AUX_DSP_CTRL]
#endif /* ARC_FEATURE_DSP */
#endif /* ARC_FEATURE_FPU_DSP_CONTEXT */
.endm
/* macro to clear scratch regs */
.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
#if ARC_FEATURE_FPU || ARC_FEATURE_DSP || ARC_FEATURE_MPU_OPTION_NUM > 6
mov r59, 0
mov r58, 0
#endif
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 to save r0 to r12 */
.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 to restore r0 to r12 */
.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 to save code density regs */
.macro SAVE_CODE_DENSITY
PUSHAX AUX_JLI_BASE
PUSHAX AUX_LDI_BASE
PUSHAX AUX_EI_BASE
.endm
/* macro to restore code density regs */
.macro RESTORE_CODE_DENSITY
POPAX AUX_EI_BASE
POPAX AUX_LDI_BASE
POPAX AUX_JLI_BASE
.endm
/* macro to save all non-caller saved regs */
.macro SAVE_NONSCRATCH_REGS
/* caller saved regs are saved by caller function */
PUSH gp
PUSH fp
PUSH blink
SAVE_CALLEE_REGS
.endm
/* macro to restore all non-caller saved regs */
.macro RESTORE_NONSCRATCH_REGS
RESTORE_CALLEE_REGS
POP blink
POP fp
POP gp
.endm
/* macro to save regs in firq */
.macro SAVE_FIQ_EXC_REGS
#ifndef ARC_FEATURE_RGF_BANKED_REGS
SAVE_R0_TO_R12
SAVE_R58_R59
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_RGF_BANKED_REGS == 8 || \
ARC_FEATURE_RGF_BANKED_REGS == 16
#ifndef ARC_FEATURE_RF16
PUSH r4
PUSH r5
PUSH r6
PUSH r7
PUSH r8
PUSH r9
#endif
#endif
#if ARC_FEATURE_RGF_BANKED_REGS == 4 || ARC_FEATURE_RGF_BANKED_REGS == 8
PUSH r10
PUSH r11
#endif
#if ARC_FEATURE_RGF_BANKED_REGS == 4
PUSH r12
#endif
SAVE_R58_R59
#if ARC_FEATURE_RGF_BANKED_REGS == 4 || ARC_FEATURE_RGF_BANKED_REGS == 8
PUSH gp
PUSH fp
PUSH r30 /* general purpose */
PUSH blink
#endif
#endif /* #ifndef ARC_FEATURE_RGF_BANKED_REGS */
#if ARC_FEATURE_CODE_DENSITY
SAVE_CODE_DENSITY
#endif
SAVE_LP_REGS
.endm
/* macro to restore reg in firq */
.macro RESTORE_FIQ_EXC_REGS
RESTORE_LP_REGS
#if ARC_FEATURE_CODE_DENSITY
RESTORE_CODE_DENSITY
#endif
#ifndef ARC_FEATURE_RGF_BANKED_REGS
POP blink
POP r30
POP fp
POP gp
RESTORE_R58_R59
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_RGF_BANKED_REGS == 8
POP blink
POP r30
POP fp
POP gp
#endif
RESTORE_R58_R59
#if ARC_FEATURE_RGF_BANKED_REGS == 4
POP r12
#endif
#if ARC_FEATURE_RGF_BANKED_REGS == 4 || ARC_FEATURE_RGF_BANKED_REGS == 8
POP r11
POP r10
#endif
#if ARC_FEATURE_RGF_BANKED_REGS == 4 || ARC_FEATURE_RGF_BANKED_REGS == 8 || \
ARC_FEATURE_RGF_BANKED_REGS == 16
#ifndef ARC_FEATURE_RF16
POP r9
POP r8
POP r7
POP r6
POP r5
POP r4
#endif
#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
SAVE_R58_R59
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
RESTORE_R58_R59
POP r12
.endm
#if ARC_FEATURE_SEC_PRESENT
/* 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
#if ARC_FEATURE_CODE_DENSITY
SAVE_CODE_DENSITY
#endif
SAVE_LP_REGS
PUSH r12
SAVE_R58_R59
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
RESTORE_R58_R59
POP r12
RESTORE_LP_REGS
#if 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
#if 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
#if 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
SAVE_R58_R59
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
RESTORE_R58_R59
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
#if ARC_FEATURE_CODE_DENSITY
RESTORE_CODE_DENSITY
#endif
POPAX AUX_ERRET
POPAX AUX_ERSTATUS
#if ARC_FEATURE_CODE_DENSITY
ld.as r10, [sp, -11] /* restore r10 */
#else
ld.as r10, [sp, -8]
#endif
.endm
#endif /* ARC_FEATURE_SEC_PRESENT */
#endif /* __ASSEMBLY__ */
#endif /* H_ARC_ASM_COMMON */
/** @endcond */

View File

@@ -1,498 +0,0 @@
/* ------------------------------------------
* 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.
*
--------------------------------------------- */
/**
* @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 H_ARC_BUILTIN
#define H_ARC_BUILTIN
#include "embARC_toolchain.h"
#include "arc/arc.h"
#ifndef __ASSEMBLY__
#ifdef __cplusplus
extern "C" {
#endif
#if defined (__MW__) /* Metaware toolchain */
#elif defined (__GNU__) /* GNU toolchain */
#endif
/**
* @brief arc_compiler_usually(expr) evaluates expression expr and
* informs the compiler that the value is usually true.
*/
#define arc_compiler_usually(a) __builtin_expect(!!(a), 1)
/**
* @brief arc_compiler_rarely(expr) evaluates expression expr and
* informs the compiler that the value is rarely true.
*/
#define arc_compiler_rarely(a) __builtin_expect(!!(a), 0)
/**
* @fn void arc_mb(void)
* @brief Do memory barrier
*
*/
Inline void arc_mb(void)
{
Asm("dmb 3\n" : : : "memory");
}
/**
* @fn void arc_rmb(void)
* @brief Read memory barrier
*
*/
Inline void arc_rmb(void)
{
Asm("dmb 1\n" : : : "memory");
}
/**
* @fn void arc_wmb(void)
* @brief Write memory barrier
*
*/
Inline void arc_wmb(void)
{
Asm("dmb 2\n" : : : "memory");
}
/**
* @fn uint32_t arc_aux_read(uint32_t aux)
* @brief Read auxiliary register
*
* @param aux auxiliary register address
* @return value of auxiliary register
*/
Inline uint32_t arc_aux_read(uint32_t aux)
{
uint32_t ret;
Asm("lr %0, [%1]"
: "=r" (ret)
: "r" (aux));
return ret;
}
/**
* @fn void arc_aux_write(uint32_t aux, uint32_t val)
* @brief Write auxiliary register
*
* @param aux auxiliary register address
* @param val Value to write
*/
Inline void arc_aux_write(uint32_t aux, uint32_t val)
{
Asm(
"sr %0, [%1] \n"
:
: "ir" (val), "r" (aux));
}
/**
* @fn void arc_brk(void)
* @brief Call brk instruction
* stop the core through a brk instruction
*/
Inline void arc_brk(void)
{
Asm("brk");
}
/**
* @fn void arc_sync(void)
* @brief Call sync instruction
*
*/
Inline void arc_sync(void)
{
Asm("sync");
}
/**
* @fn void arc_kflag(uint32_t flag)
* @brief Call kflag instruction to change status32
*
* @param flag Flag to set in status32
*/
Inline void arc_kflag(uint32_t flag)
{
/*sr cannot write AUX_STATUS32 */
Asm("kflag %0" ::"ir" (flag));
}
/**
* @fn void arc_nop(void)
* @brief Call nop_s function
* flush the pipeline by nop_s instruction
*/
Inline void arc_nop(void)
{
Asm("nop_s");
}
/**
* @fn uint32_t arc_clri(void)
* @brief Call clri instruction
* call a clri instruction to disable interrupt
* @return interrupt related bits in status32
*/
Inline uint32_t arc_clri(void)
{
uint32_t v;
Asm("clri %0" : "=r" (v):: "memory");
return v;
}
/**
* @fn void arc_seti(uint32_t key)
* @brief Call seti instruction
* call a set instruction to change interrupt status
* @param key interrupt status
*/
Inline void arc_seti(uint32_t key)
{
Asm("seti %0" : : "ir" (key) : "memory");
}
/**
* @fn uint32_t arc_swap32(uint32_t val)
* @brief Swap bytes order of a 32-bits value
*
* @param val Target value
* @return Swapped value
*/
Inline uint32_t arc_swap32(uint32_t val)
{
uint32_t v;
Asm("swape %0, %1" : "=r" (v) : "r" (val));
return v;
}
/**
* @fn uint16_t arc_swap16(uint32_t val)
* @brief Swap bytes order of a 32-bits value and return high 16-bits
*
* @param val Target value
* @return High 16 bits of the swapped value
*/
Inline uint16_t arc_swap16(uint32_t val)
{
uint32_t temp;
uint32_t v;
Asm("swape %0, %1" : "=r" (temp) : "r" (val));
Asm("lsr16 %0, %1" : "=r" (v) : "r" (temp));
return (uint16_t)v;
}
/**
* @name cache related helper function
* @{
*/
/**
* @fn arc_read_uncached_32(void *ptr)
* @brief Read memory and bypass the cache
* @param ptr Memory address
* @return data 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;
}
/**
* @fn arc_write_uncached_32(void *ptr, uint32_t data)
* @brief Write memory and bypass the cache
* @param ptr memory address
* @param data value to be written
*/
Inline void arc_write_uncached_32(void *ptr, uint32_t data)
{
Asm("st.di %0, [%1]" :: "r" (data), "r" (ptr));
}
/**
* @fn arc_read_cached_32(void *ptr)
* @brief Read memory with cache
* @param ptr Memory address
* @returns data 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;
}
/**
* @fn void arc_write_cached_32(void *ptr, uint32_t data)
* @brief Read memory with cache
* @param ptr Memory address
* @param data Data to be written
*/
Inline void arc_write_cached_32(void *ptr, uint32_t data)
{
Asm("st %0, [%1]" :: "r" (data), "r" (ptr));
}
/**
* @fn int32_t arc_goto_main(int32_t argc, char **argv)
* @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(int32_t argc, char **argv)
{
int32_t ret;
Asm(
"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 (int32_t)ret;
}
/**
* @fn uint32_t arc_find_msb(uint32_t val)
* @brief Find most significant bit set in a 32-bit word
*
* This routine finds the first bit set starting from the most significant bit
* in the argument passed in and returns the index of that bit. Bits are
* numbered starting at 1 from the least significant bit. A return value of
* zero indicates that the value passed is zero.
*
* @return Most significant bit set, 0 if @a val is 0
*/
Inline uint32_t arc_find_msb(uint32_t val)
{
uint32_t bit;
Asm(
/* BITSCAN_OPTION is required */
"fls.f %0, %1;\n"
"add.nz %0, %0, 1;\n"
: "=r" (bit)
: "r" (val));
return bit;
}
/**
* @fn uint32_t arc_find_lsb(uint32_t val)
* @brief Find least significant bit set in a 32-bit word
*
* This routine finds the first bit set starting from the least significant bit
* in the argument passed in and returns the index of that bit. Bits are
* numbered starting at 1 from the least significant bit. A return value of
* zero indicates that the value passed is zero.
*
* @return Least significant bit set, 0 if @a val is 0
*/
Inline uint32_t arc_find_lsb(uint32_t val)
{
uint32_t bit;
Asm(
/* BITSCAN_OPTION is required */
"ffs.f %0, %1;\n"
"add.nz %0, %0, 1;\n"
"mov.z %0, 0;\n"
: "=&r" (bit)
: "r" (val));
return bit;
}
/**
* @fn uint32_t arc_core_id(void)
* @brief Read core id
*
* @return Core id
*/
Inline uint32_t arc_core_id(void)
{
uint32_t ret;
Asm(
"lr %0, [%1]\n"
"xbfu %0, %0, 0xe8\n"
: "=r" (ret)
: "i" (AUX_IDENTITY));
return ret;
}
/**
* @fn void arc_stack_check_enable(void)
* @brief Enable hardware stack checking
*/
Inline void arc_stack_check_enable(void)
{
#if ARC_FEATURE_SEC_PRESENT
Asm(
"bset %0, %0, %1\n"
"sflag r0\n"
:
: "r" (arc_aux_read(AUX_SEC_STAT)), "i" (AUX_SEC_STAT_BIT_SSC));
#else
Asm(
"bset %0, %0, %1\n"
"kflag r0\n"
:
: "r" (arc_aux_read(AUX_STATUS32)), "i" (AUX_STATUS_BIT_SC));
#endif
}
/**
* @fn void arc_stack_check_disable(void)
* @brief Disable hardware stack checking
*/
Inline void arc_stack_check_disable(void)
{
#if ARC_FEATURE_SEC_PRESENT
Asm(
"bclr %0, %0, %1\n"
"sflag r0\n"
:
: "r" (arc_aux_read(AUX_SEC_STAT)), "i" (AUX_SEC_STAT_BIT_SSC));
#else
Asm(
"bclr %0, %0, %1\n"
"kflag r0\n"
:
: "r" (arc_aux_read(AUX_STATUS32)), "i" (AUX_STATUS_BIT_SC));
#endif
}
/**
* @fn void arc_kernel_stack_check_configure(uint32_t top, uint32_t base)
* @brief Configure stack checking in kernel mode
*
* @param top Top of stack
* @param base Base of stack
*/
Inline void arc_kernel_stack_check_configure(uint32_t top, uint32_t base)
{
#if ARC_FEATURE_SEC_PRESENT
arc_aux_write(AUX_S_KSTACK_TOP, top);
arc_aux_write(AUX_S_KSTACK_BASE, base);
#else
arc_aux_write(AUX_KSTACK_TOP, top);
arc_aux_write(AUX_KSTACK_BASE, base);
#endif
}
/**
* @fn uint32_t arc_is_user_mode(void)
* @brief Check whether processor is in user mode
* this function relies on AUX_STATUS_BIT_US set in privileged mode first
* @return 1 user mode, 0 privileged mode
*/
Inline uint32_t arc_is_user_mode(void)
{
uint32_t status;
Asm(
"lr %0, [%1]\n"
: "=r" (status)
: "i" (AUX_STATUS32)
: "memory");
return !(status & AUX_STATUS_MASK_US) ? 1 : 0;
}
/**
* @brief Go to user mode
* It's suggested to disable interrupt before call this function especially
* when using current stack, i.e., sp == 0. Because interrupt handling requires
* kernel mode stack which is different with user mode stack.
* @param target Target address to run in user mode, 0 means next
* line of code
* @param sp Stack where the target address runs, 0 means using
* current stack
*/
extern void arc_goto_usermode(void *target, uint32_t *sp);
/**
* @brief Go to kernel mode
* this function uses trap exception to do switch from user mode to kernel mode,
* please install exc_entry_arc_goto_kernelmode for trap exception before call this
* function
* @param target Target address to run in kernel mode, 0 means next line of code
* @param sp Stack where the target address runs, 0 means using current stack
*/
extern void arc_goto_kernelmode(void *target, uint32_t *sp);
/**
* @brief Trap exception entry used for arc_goto_kernelmode
*
* install this entry for trap exception before call arc_goto_kernelmode
*/
extern void exc_entry_arc_goto_kernelmode(void);
#ifdef __cplusplus
}
#endif
#endif /* __ASSEMBLY__ */
/** @} */
#endif /* H_ARC_BUILTIN */
/** @} */

View File

@@ -1,331 +0,0 @@
/* ------------------------------------------
* 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.
*
--------------------------------------------- */
/**
* @file
* @ingroup ARC_HAL_MISC_CACHE
* @brief Header file of cache module
*/
#ifndef H_ARC_CACHE
#define H_ARC_CACHE
#include "arc/arc_builtin.h"
#include "arc/arc_exception.h"
/**
* @addtogroup ARC_HAL_MISC_CACHE
* @{
*/
/**
* @name Marco definitions for cache control
* @todo These 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 Marco definitions for data cache control
* @todo These 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 */
/** @} */
#ifndef __ASSEMBLY__
#ifdef __cplusplus
extern "C" {
#endif
/**
* @name instruction cache related inline function
* @{
*/
/**
* @fn uint32_t icache_available(void)
* @brief Check whether instruction cache is available,
* @return 0 for not available, >0 for available
*/
Inline uint32_t icache_available(void)
{
return (arc_aux_read(AUX_BCR_I_CACHE) & 0xF);
}
/**
* @fn void icache_enable(uint32_t icache_en_mask)
* @brief Enable instruction cache
* @param 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);
}
/**
* @fn void icache_disable(void)
* @brief Disable instruction cache
*/
Inline void icache_disable(void)
{
arc_aux_write(AUX_IC_CTRL, IC_CTRL_IC_DISABLE);
}
/**
* @fn void icache_invalidate(void)
* @brief Invalidate the entire instruction cache
*/
Inline void icache_invalidate(void)
{
/* invalidate the entire icache */
arc_aux_write(AUX_IC_IVIC, 0);
arc_nop();
arc_nop();
arc_nop();
}
/**
* @fn void icache_invalidate_line(uint32_t address)
* @brief Invalidate specific cache line
* @param address Memory address
*/
Inline void icache_invalidate_line(uint32_t address)
{
arc_aux_write(AUX_IC_IVIL, address);
/* the 3 nops are required by ARCv2 ISA */
arc_nop();
arc_nop();
arc_nop();
}
/**
* @fn int32_t icache_lock_line(uint32_t address)
* @brief Lock specific cache line
* @param address Memory address
* @return 0, succeeded, -1, failed
*/
Inline int32_t icache_lock_line(uint32_t address)
{
arc_aux_write(AUX_IC_LIL, address);
if (arc_aux_read(AUX_IC_CTRL) & IC_CTRL_OP_SUCCEEDED) {
return 0;
} else {
return -1;
}
}
/**
* @fn void icache_access_mode(uint32_t mode)
* @brief Set icache access mode
* @param mode access mode, 1: indirect access 0:direct access
*/
Inline void icache_access_mode(uint32_t mode)
{
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
* @{
*/
/**
* @fn uint32_t dcache_available(void)
* @brief Check whether data cache is available,
* 0 for not available, >0 for available
*/
Inline uint32_t dcache_available(void)
{
return (arc_aux_read(AUX_BCR_D_CACHE) & 0xF);
}
/**
* @fn void dcache_invalidate(void)
* @brief Invalidate the entire data cache
*/
Inline void dcache_invalidate(void)
{
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);
}
/**
* @fn void dcache_invalidate_line(uint32_t address)
* @brief Invalidate the specific cache line
* @param address Memory address
*/
Inline void dcache_invalidate_line(uint32_t address)
{
arc_aux_write(AUX_DC_IVDL, address);
arc_nop();
arc_nop();
arc_nop();
}
/**
* @fn void dcache_enable(uint32_t dcache_en_mask)
* @brief Enable data cache
* @param dcache_en_mask Operation mask
*/
Inline void dcache_enable(uint32_t dcache_en_mask)
{
arc_aux_write(AUX_DC_CTRL, dcache_en_mask);
}
/**
* @fn void dcache_disable(void)
* @brief Disable data cache
*/
Inline void dcache_disable(void)
{
arc_aux_write(AUX_DC_CTRL, DC_CTRL_DC_DISABLE);
}
/**
* @fn void dcache_flush(void)
* @brief Flush data cache
*/
Inline void dcache_flush(void)
{
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);
}
/**
* @fn void dcache_flush_line(uint32_t address)
* @brief Flush the specific data cache line
* @param address Memory address
*/
Inline void dcache_flush_line(uint32_t address)
{
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);
}
/**
* @fn int32_t dcache_lock_line(uint32_t address)
* @brief Lock the specific data cache line
* @param address Memory address
* @return 0, succeeded, -1, failed
*/
Inline int32_t dcache_lock_line(uint32_t address)
{
arc_aux_write(AUX_DC_LDL, address);
if (arc_aux_read(AUX_DC_CTRL) & DC_CTRL_OP_SUCCEEDED) {
return 0;
} else {
return -1;
}
}
/**
* @fn void dcache_access_mode(uint32_t mode)
* @brief Set dcache access mode
* @param mode Access mode, 1: indirect access 0:direct access
*/
Inline void dcache_access_mode(uint32_t mode)
{
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));
}
}
/** @} */
/**
* @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 /* __ASSEMBLY__ */
/** @} */
#endif /* H_ARC_CACHE */
/** @} end of group ARC_HAL_MISC_CACHE */

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