forked from TencentOS/TencentOS-tiny
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:
parent
13eaef3d46
commit
0d4593ee5e
|
|
@ -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);
|
||||
|
|
@ -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
|
||||
|
|
@ -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_ */
|
||||
|
||||
|
|
@ -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
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -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_ */
|
||||
|
|
@ -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;
|
||||
|
||||
|
||||
|
|
@ -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]
|
||||
|
|
@ -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 */
|
||||
|
||||
|
|
@ -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 */
|
||||
|
|
@ -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 */
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
||||
|
|
@ -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)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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=""${workspace_loc:/blinky}""/>
|
||||
|
||||
<listOptionValue builtIn="false" value=""${workspace_loc:/blinky/tencentos/kernel/core/include}""/>
|
||||
|
||||
<listOptionValue builtIn="false" value=""${workspace_loc:/blinky/tencentos/kernel/pm/include}""/>
|
||||
|
||||
<listOptionValue builtIn="false" value=""${workspace_loc:/blinky/tencentos/kernel/hal/include}""/>
|
||||
|
||||
<listOptionValue builtIn="false" value=""${workspace_loc:/blinky/tencentos/arch/arc/nsim/common/include}""/>
|
||||
|
||||
<listOptionValue builtIn="false" value=""${workspace_loc:/blinky/tencentos/arch/arc/nsim/em/gcc}""/>
|
||||
|
||||
<listOptionValue builtIn="false" value=""${workspace_loc:/blinky/tencentos/board/ARC_NSIM_EM/TOS-CONFIG}""/>
|
||||
|
||||
<listOptionValue builtIn="false" value=""${workspace_loc:/blinky/tencentos/osal/cmsis_os}""/>
|
||||
|
||||
<listOptionValue builtIn="false" value=""${workspace_loc:/blinky/tencentos/board/ARC_NSIM_EM/BSP/Inc}""/>
|
||||
|
||||
<listOptionValue builtIn="false" value=""${workspace_loc:/blinky/tencentos/platform/vendor_bsp/embarc_bsp/include}""/>
|
||||
|
||||
<listOptionValue builtIn="false" value=""${workspace_loc:/blinky/tencentos/platform/vendor_bsp/embarc_bsp/library}""/>
|
||||
|
||||
</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=""${workspace_loc:/blinky}""/>
|
||||
<listOptionValue builtIn="false" value=""${workspace_loc:/blinky/tencentos/kernel/core/include}""/>
|
||||
|
||||
<listOptionValue builtIn="false" value=""${workspace_loc:/blinky/tencentos/kernel/pm/include}""/>
|
||||
|
||||
<listOptionValue builtIn="false" value=""${workspace_loc:/blinky/tencentos/kernel/hal/include}""/>
|
||||
|
||||
<listOptionValue builtIn="false" value=""${workspace_loc:/blinky/tencentos/arch/arc/nsim/common/include}""/>
|
||||
|
||||
<listOptionValue builtIn="false" value=""${workspace_loc:/blinky/tencentos/arch/arc/nsim/em/gcc}""/>
|
||||
|
||||
<listOptionValue builtIn="false" value=""${workspace_loc:/blinky/tencentos/board/ARC_NSIM_EM/TOS-CONFIG}""/>
|
||||
|
||||
<listOptionValue builtIn="false" value=""${workspace_loc:/blinky/tencentos/osal/cmsis_os}""/>
|
||||
|
||||
<listOptionValue builtIn="false" value=""${workspace_loc:/blinky/tencentos/board/ARC_NSIM_EM/BSP/Inc}""/>
|
||||
|
||||
<listOptionValue builtIn="false" value=""${workspace_loc:/blinky/tencentos/platform/vendor_bsp/embarc_bsp/include}""/>
|
||||
|
||||
<listOptionValue builtIn="false" value=""${workspace_loc:/blinky/tencentos/platform/vendor_bsp/embarc_bsp/library}""/>
|
||||
|
||||
</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>
|
||||
|
|
@ -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**启动调试
|
||||
|
|
@ -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 ***
|
||||
|
|
@ -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="<?xml version="1.0" encoding="UTF-8" standalone="no"?><contentList/>"/>
|
||||
<stringAttribute key="org.eclipse.cdt.launch.GLOBAL_VARIABLES" value="<?xml version="1.0" encoding="UTF-8" standalone="no"?> <globalVariableList/> "/>
|
||||
<stringAttribute key="org.eclipse.cdt.launch.MEMORY_BLOCKS" value="<?xml version="1.0" encoding="UTF-8" standalone="no"?> <memoryBlockExpressionList/> "/>
|
||||
<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="<?xml version="1.0" encoding="UTF-8" standalone="no"?> <memoryBlockExpressionList context="reserved-for-future-use"/> "/>
|
||||
<stringAttribute key="process_factory_id" value="org.eclipse.cdt.dsf.gdb.GdbProcessFactory"/>
|
||||
</launchConfiguration>
|
||||
|
|
@ -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);
|
||||
}
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
||||
|
|
@ -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>
|
||||
|
|
@ -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>
|
||||
|
|
@ -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
|
||||
|
|
@ -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.
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1 @@
|
|||
Subproject commit 7595aae3c2cec9cd4f2b4fe4de60b7a625545345
|
||||
|
|
@ -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();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
||||
|
|
@ -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 */
|
||||
|
|
@ -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 */
|
||||
|
|
@ -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);
|
||||
}
|
||||
|
|
@ -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
|
||||
}
|
||||
|
|
@ -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
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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 */
|
||||
|
||||
/** }@*/
|
||||
|
|
@ -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) {
|
||||
;
|
||||
}
|
||||
}
|
||||
|
|
@ -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 */
|
||||
|
|
@ -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;
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -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 */
|
||||
|
|
@ -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 */
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -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
|
||||
|
|
@ -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, ¶m);
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
|
@ -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.
|
||||
*
|
||||
--------------------------------------------- */
|
||||
|
|
@ -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, ¶m);
|
||||
|
||||
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, ¶m);
|
||||
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, ¶m);
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
|
@ -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
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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 */
|
||||
|
|
@ -1,2 +0,0 @@
|
|||
DEV_CSRCDIR += $(EMBARC_ROOT)/device/peripheral/adc/adc088s022
|
||||
DEV_INCDIR += $(EMBARC_ROOT)/device/peripheral/adc/adc088s022
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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 */
|
||||
|
|
@ -1,2 +0,0 @@
|
|||
DEV_CSRCDIR += $(EMBARC_ROOT)/device/peripheral/audio/max9880a
|
||||
DEV_INCDIR += $(EMBARC_ROOT)/device/peripheral/audio/max9880a
|
||||
|
|
@ -1,2 +0,0 @@
|
|||
DEV_CSRCDIR += $(EMBARC_ROOT)/device/peripheral/flash/fl256s
|
||||
DEV_INCDIR += $(EMBARC_ROOT)/device/peripheral/flash/fl256s
|
||||
|
|
@ -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, ®, 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, ®, 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);
|
||||
}
|
||||
|
|
@ -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 */
|
||||
|
|
@ -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);
|
||||
}
|
||||
|
|
@ -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 */
|
||||
|
|
@ -1,2 +0,0 @@
|
|||
DEV_CSRCDIR += $(EMBARC_ROOT)/device/peripheral/flash/w25qxx
|
||||
DEV_INCDIR += $(EMBARC_ROOT)/device/peripheral/flash/w25qxx
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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 */
|
||||
|
|
@ -1,2 +0,0 @@
|
|||
DEV_CSRCDIR += $(EMBARC_ROOT)/device/peripheral/io/cy8c95xx
|
||||
DEV_INCDIR += $(EMBARC_ROOT)/device/peripheral/io/cy8c95xx
|
||||
|
|
@ -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__
|
||||
|
|
@ -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
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -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_ */
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -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_ */
|
||||
|
||||
|
|
@ -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
|
||||
|
|
@ -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 */
|
||||
|
|
@ -1,2 +0,0 @@
|
|||
DEV_CSRCDIR += $(EMBARC_ROOT)/device/peripheral/sensor/imu/mpu9250
|
||||
DEV_INCDIR += $(EMBARC_ROOT)/device/peripheral/sensor/imu/mpu9250
|
||||
|
|
@ -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 */
|
||||
|
||||
/** @} */
|
||||
|
|
@ -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 */
|
||||
|
|
@ -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 */
|
||||
/** @} */
|
||||
|
|
@ -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
Loading…
Reference in New Issue