From 3639963a9783dc3f06804bd7dff9283010edb372 Mon Sep 17 00:00:00 2001 From: Huang bo Date: Tue, 16 Nov 2021 18:32:11 +0800 Subject: [PATCH 01/24] =?UTF-8?q?=E6=B7=BB=E5=8A=A0TMS320C6678=E5=A4=84?= =?UTF-8?q?=E7=90=86=E5=99=A8=EF=BC=8Ckeystone=E6=9E=B6=E6=9E=84=E5=BA=95?= =?UTF-8?q?=E5=B1=82=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- bsp/ti-c6678/.ccsproject | 12 + bsp/ti-c6678/.cproject | 160 + bsp/ti-c6678/.project | 154 + .../org.eclipse.cdt.codan.core.prefs | 3 + .../org.eclipse.cdt.debug.core.prefs | 2 + .../org.eclipse.core.resources.prefs | 10 + bsp/ti-c6678/KeyStone.cmd | 47 + bsp/ti-c6678/applications/board.c | 60 + bsp/ti-c6678/applications/board.h | 20 + bsp/ti-c6678/applications/main.c | 99 + bsp/ti-c6678/driver/KeyStone_common.c | 4355 +++++++++++++++++ bsp/ti-c6678/driver/KeyStone_common.h | 1090 +++++ bsp/ti-c6678/driver/drv_timer.c | 55 + bsp/ti-c6678/driver/drv_timer.h | 19 + bsp/ti-c6678/rtconfig.h | 122 + bsp/ti-c6678/rtconfig_project.h | 23 + libcpu/ti-dsp/c6x/SConscript | 14 + libcpu/ti-dsp/c6x/c66xx.h | 106 + libcpu/ti-dsp/c6x/context.asm | 312 ++ libcpu/ti-dsp/c6x/cpuport.c | 225 + libcpu/ti-dsp/c6x/inct.asm | 374 ++ libcpu/ti-dsp/c6x/interrupt.c | 90 + libcpu/ti-dsp/c6x/interrupt.h | 24 + libcpu/ti-dsp/c6x/stack.asm | 103 + libcpu/ti-dsp/c6x/trap.c | 352 ++ libcpu/ti-dsp/c6x/trap.h | 76 + libcpu/ti-dsp/c6x/vector.asm | 95 + 27 files changed, 8002 insertions(+) create mode 100644 bsp/ti-c6678/.ccsproject create mode 100644 bsp/ti-c6678/.cproject create mode 100644 bsp/ti-c6678/.project create mode 100644 bsp/ti-c6678/.settings/org.eclipse.cdt.codan.core.prefs create mode 100644 bsp/ti-c6678/.settings/org.eclipse.cdt.debug.core.prefs create mode 100644 bsp/ti-c6678/.settings/org.eclipse.core.resources.prefs create mode 100644 bsp/ti-c6678/KeyStone.cmd create mode 100644 bsp/ti-c6678/applications/board.c create mode 100644 bsp/ti-c6678/applications/board.h create mode 100644 bsp/ti-c6678/applications/main.c create mode 100644 bsp/ti-c6678/driver/KeyStone_common.c create mode 100644 bsp/ti-c6678/driver/KeyStone_common.h create mode 100644 bsp/ti-c6678/driver/drv_timer.c create mode 100644 bsp/ti-c6678/driver/drv_timer.h create mode 100644 bsp/ti-c6678/rtconfig.h create mode 100644 bsp/ti-c6678/rtconfig_project.h create mode 100644 libcpu/ti-dsp/c6x/SConscript create mode 100644 libcpu/ti-dsp/c6x/c66xx.h create mode 100644 libcpu/ti-dsp/c6x/context.asm create mode 100644 libcpu/ti-dsp/c6x/cpuport.c create mode 100644 libcpu/ti-dsp/c6x/inct.asm create mode 100644 libcpu/ti-dsp/c6x/interrupt.c create mode 100644 libcpu/ti-dsp/c6x/interrupt.h create mode 100644 libcpu/ti-dsp/c6x/stack.asm create mode 100644 libcpu/ti-dsp/c6x/trap.c create mode 100644 libcpu/ti-dsp/c6x/trap.h create mode 100644 libcpu/ti-dsp/c6x/vector.asm diff --git a/bsp/ti-c6678/.ccsproject b/bsp/ti-c6678/.ccsproject new file mode 100644 index 0000000000..82f98bbb00 --- /dev/null +++ b/bsp/ti-c6678/.ccsproject @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/bsp/ti-c6678/.cproject b/bsp/ti-c6678/.cproject new file mode 100644 index 0000000000..aef3a8c240 --- /dev/null +++ b/bsp/ti-c6678/.cproject @@ -0,0 +1,160 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/bsp/ti-c6678/.project b/bsp/ti-c6678/.project new file mode 100644 index 0000000000..d1c8afd3a3 --- /dev/null +++ b/bsp/ti-c6678/.project @@ -0,0 +1,154 @@ + + + ti-c6678 + + + + + + org.eclipse.cdt.managedbuilder.core.genmakebuilder + + + + + org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder + full,incremental, + + + + + + com.ti.ccstudio.core.ccsNature + org.eclipse.cdt.core.cnature + org.eclipse.cdt.managedbuilder.core.managedBuildNature + org.eclipse.cdt.core.ccnature + org.eclipse.cdt.managedbuilder.core.ScannerConfigNature + + + + SConscript + 1 + PARENT-2-PROJECT_LOC/src/SConscript + + + clock.c + 1 + PARENT-2-PROJECT_LOC/src/clock.c + + + components.c + 1 + PARENT-2-PROJECT_LOC/src/components.c + + + context.asm + 1 + PARENT-2-PROJECT_LOC/libcpu/ti-dsp/c6x/context.asm + + + cpu.c + 1 + PARENT-2-PROJECT_LOC/src/cpu.c + + + cpuport.c + 1 + PARENT-2-PROJECT_LOC/libcpu/ti-dsp/c6x/cpuport.c + + + device.c + 1 + PARENT-2-PROJECT_LOC/src/device.c + + + idle.c + 1 + PARENT-2-PROJECT_LOC/src/idle.c + + + inct.asm + 1 + PARENT-2-PROJECT_LOC/libcpu/ti-dsp/c6x/inct.asm + + + interrupt.c + 1 + PARENT-2-PROJECT_LOC/libcpu/ti-dsp/c6x/interrupt.c + + + ipc.c + 1 + PARENT-2-PROJECT_LOC/src/ipc.c + + + irq.c + 1 + PARENT-2-PROJECT_LOC/src/irq.c + + + kservice.c + 1 + PARENT-2-PROJECT_LOC/src/kservice.c + + + mem.c + 1 + PARENT-2-PROJECT_LOC/src/mem.c + + + memheap.c + 1 + PARENT-2-PROJECT_LOC/src/memheap.c + + + mempool.c + 1 + PARENT-2-PROJECT_LOC/src/mempool.c + + + object.c + 1 + PARENT-2-PROJECT_LOC/src/object.c + + + scheduler.c + 1 + PARENT-2-PROJECT_LOC/src/scheduler.c + + + signal.c + 1 + PARENT-2-PROJECT_LOC/src/signal.c + + + slab.c + 1 + PARENT-2-PROJECT_LOC/src/slab.c + + + stack.asm + 1 + PARENT-2-PROJECT_LOC/libcpu/ti-dsp/c6x/stack.asm + + + thread.c + 1 + PARENT-2-PROJECT_LOC/src/thread.c + + + timer.c + 1 + PARENT-2-PROJECT_LOC/src/timer.c + + + trap.c + 1 + PARENT-2-PROJECT_LOC/libcpu/ti-dsp/c6x/trap.c + + + vector.asm + 1 + PARENT-2-PROJECT_LOC/libcpu/ti-dsp/c6x/vector.asm + + + diff --git a/bsp/ti-c6678/.settings/org.eclipse.cdt.codan.core.prefs b/bsp/ti-c6678/.settings/org.eclipse.cdt.codan.core.prefs new file mode 100644 index 0000000000..f653028c53 --- /dev/null +++ b/bsp/ti-c6678/.settings/org.eclipse.cdt.codan.core.prefs @@ -0,0 +1,3 @@ +eclipse.preferences.version=1 +inEditor=false +onBuild=false diff --git a/bsp/ti-c6678/.settings/org.eclipse.cdt.debug.core.prefs b/bsp/ti-c6678/.settings/org.eclipse.cdt.debug.core.prefs new file mode 100644 index 0000000000..2adc7b1dde --- /dev/null +++ b/bsp/ti-c6678/.settings/org.eclipse.cdt.debug.core.prefs @@ -0,0 +1,2 @@ +eclipse.preferences.version=1 +org.eclipse.cdt.debug.core.toggleBreakpointModel=com.ti.ccstudio.debug.CCSBreakpointMarker diff --git a/bsp/ti-c6678/.settings/org.eclipse.core.resources.prefs b/bsp/ti-c6678/.settings/org.eclipse.core.resources.prefs new file mode 100644 index 0000000000..83b10321a8 --- /dev/null +++ b/bsp/ti-c6678/.settings/org.eclipse.core.resources.prefs @@ -0,0 +1,10 @@ +eclipse.preferences.version=1 +encoding//Debug/applications/subdir_rules.mk=UTF-8 +encoding//Debug/applications/subdir_vars.mk=UTF-8 +encoding//Debug/driver/subdir_rules.mk=UTF-8 +encoding//Debug/driver/subdir_vars.mk=UTF-8 +encoding//Debug/makefile=UTF-8 +encoding//Debug/objects.mk=UTF-8 +encoding//Debug/sources.mk=UTF-8 +encoding//Debug/subdir_rules.mk=UTF-8 +encoding//Debug/subdir_vars.mk=UTF-8 diff --git a/bsp/ti-c6678/KeyStone.cmd b/bsp/ti-c6678/KeyStone.cmd new file mode 100644 index 0000000000..0f30bc506e --- /dev/null +++ b/bsp/ti-c6678/KeyStone.cmd @@ -0,0 +1,47 @@ +/****************************************************************************/ +/* */ +/* M6678.cmd */ +/* Copyright (c): NUDT */ +/* */ +/* */ +/* Description: This file is a sample linker command file that can be */ +/* used for linking programs built with the C compiler and */ +/* running the resulting .out file on an M6678 */ +/* device. Use it as a guideline. You will want to */ +/* change the memory layout to match your specific C6xxx */ +/* target system. You may want to change the allocation */ +/* scheme according to the size of your program. */ +/* */ +/* */ +/****************************************************************************/ + +-heap 0x800 +-stack 0x1000 + +MEMORY +{ + VECTORS: o = 0x00800000 l = 0x00000200 + LL2_CODE: o = 0x00800200 l = 0x0001FE00 + LL2_RW_DATA: o = 0x00820000 l = 0x00020000 /*set memory protection attribitue as read/write*/ +} + +SECTIONS +{ + .vecs > VECTORS + + .text > LL2_CODE + .cinit > LL2_CODE + .const > LL2_CODE + .switch > LL2_CODE + .stack > LL2_RW_DATA + GROUP + { + .neardata + .rodata + .bss + } > LL2_RW_DATA + .far > LL2_RW_DATA + .fardata > LL2_RW_DATA + .cio > LL2_RW_DATA + .sysmem > LL2_RW_DATA +} diff --git a/bsp/ti-c6678/applications/board.c b/bsp/ti-c6678/applications/board.c new file mode 100644 index 0000000000..140871fd75 --- /dev/null +++ b/bsp/ti-c6678/applications/board.c @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2021, Shenzhen Academy of Aerospace Technology + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2021-11-16 Dystopia the first version + */ + +#include "board.h" +#include "trap.h" +#include "interrupt.h" +#include "drv_timer.h" +#include "KeyStone_common.h" + +#include + +/** + * This is the timer interrupt service routine. + * + */ +void rt_hw_systick_isr(void) +{ + /* enter interrupt */ + rt_interrupt_enter(); + + rt_tick_increase(); + + /* leave interrupt */ + rt_interrupt_leave(); +} + +/** + * This function will initial board. + */ +void rt_hw_board_init(void) +{ + // initial CPU core + KeyStone_common_CPU_init(); + + // initial interrupt controller + rt_hw_interrupt_init(); + + // initial system trap + rt_trap_init(); + + // initial system timer + hw_system_timer_init(); + +#ifdef RT_USING_HEAP + /* initialize memory system */ + rt_kprintf("heap: 0x%08x - 0x%08x\n", RT_HW_HEAP_BEGIN, RT_HW_HEAP_END); + rt_system_heap_init(RT_HW_HEAP_BEGIN, RT_HW_HEAP_END); +#endif + // ...... + + hw_system_timer_start(); +} + diff --git a/bsp/ti-c6678/applications/board.h b/bsp/ti-c6678/applications/board.h new file mode 100644 index 0000000000..88e6e94e6e --- /dev/null +++ b/bsp/ti-c6678/applications/board.h @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2021, Shenzhen Academy of Aerospace Technology + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2021-11-16 Dystopia the first version + */ + +#ifndef __BOARD_H__ +#define __BOARD_H__ + +#define RT_HW_HEAP_BEGIN (void*)0x0C000000 +#define RT_HW_HEAP_END (void*)0x0C100000 + +void rt_hw_board_init(void); + +#endif /* __BOARD_H__ */ + diff --git a/bsp/ti-c6678/applications/main.c b/bsp/ti-c6678/applications/main.c new file mode 100644 index 0000000000..fd418f09f4 --- /dev/null +++ b/bsp/ti-c6678/applications/main.c @@ -0,0 +1,99 @@ +/* + * Copyright (c) 2021, Shenzhen Academy of Aerospace Technology + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2021-11-16 Dystopia the first version + */ + +#include +#include + +#include "board.h" + +void rt_init_thread_entry(void *parameter) +{ + + while(1) + { + rt_thread_sleep(10); + } +} + +void rt_my_thread_entry(void *parameter) +{ + while(1) + { + rt_thread_sleep(20); + } +} + +int rt_application_init(void) +{ + rt_thread_t tid; + + tid = rt_thread_create("init", rt_init_thread_entry, RT_NULL, 4096, 3, 200); + if (tid != RT_NULL) + { + rt_thread_startup(tid); + } else { + return -1; + } + /******************************************************************/ + tid = rt_thread_create("mythread", rt_my_thread_entry, RT_NULL, 4096, 3, 200); + if (tid != RT_NULL) + { + rt_thread_startup(tid); + } else { + return -1; + } + + return 0; +} + +/** + * This function will startup RT-Thread RTOS. + */ +void rtthread_startup(void) +{ + /* disable interrupt first */ + rt_hw_interrupt_disable(); + + /* init board */ + rt_hw_board_init(); + + /* show version */ + rt_show_version(); + + /* init timer system */ + rt_system_timer_init(); + + /* init scheduler system */ + rt_system_scheduler_init(); + + /* init application */ + rt_application_init(); + + /* init timer thread */ + rt_system_timer_thread_init(); + + /* init idle thread */ + rt_thread_idle_init(); + + /* start scheduler */ + rt_system_scheduler_start(); + + /* never reach here */ + return ; +} + +void main(void) +{ + /* startup RT-Thread RTOS */ + rtthread_startup(); + + for ( ; ; ); +} + diff --git a/bsp/ti-c6678/driver/KeyStone_common.c b/bsp/ti-c6678/driver/KeyStone_common.c new file mode 100644 index 0000000000..5807ed7aff --- /dev/null +++ b/bsp/ti-c6678/driver/KeyStone_common.c @@ -0,0 +1,4355 @@ +/****************************************************************************** + + Copyright (C), 2001-2012, Texas Instrument. + + ****************************************************************************** + File Name : KeyStone_common.c + Version : Initial Draft + Author : Brighton Feng + Created : 2010-12-12 + Last Modified : + Description : KeyStone common miscellaneous functions and definitions + History : + 1.Date : 2010-12-12 + Author : Brighton Feng + Modification: Created file + + 2.Date : 2012-10-6 + Author : Brighton Feng + Modification : Add memory protection and EDC configuration + + 3.Date : 2014-12-8 + Author : Brighton Feng + Modification : Add common device, CPU, interrupt initialization functions. + Print device information including device type, speed grade, + boot mode, required voltage, ID�� + Add EDMA enable/disable functions. + To support square wave generation by timer. +******************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include "CSL_msmc.h" +#include "CSL_msmcAux.h" +#include "KeyStone_common.h" + +/*----------------------------------------------* + * external variables * + *----------------------------------------------*/ + +/*----------------------------------------------* + * external routine prototypes * + *----------------------------------------------*/ + +/*----------------------------------------------* + * internal routine prototypes * + *----------------------------------------------*/ + +/*----------------------------------------------* + * project-wide global variables * + *----------------------------------------------*/ +CSL_XmcRegs * gpXMC_regs = (CSL_XmcRegs *) CSL_XMC_CONFIG_REGS; +CSL_CgemRegs * gpCGEM_regs = (CSL_CgemRegs *)CSL_CGEM0_5_REG_BASE_ADDRESS_REGS; +CSL_BootcfgRegs * gpBootCfgRegs = (CSL_BootcfgRegs *)CSL_BOOT_CFG_REGS; +CSL_PllcRegs * gpPLLC_regs = (CSL_PllcRegs * )CSL_PLL_CONTROLLER_REGS; +CSL_PscRegs * gpPSC_regs = (CSL_PscRegs *)CSL_PSC_REGS; +CSL_MsmcRegs * gpMSMC_regs = (CSL_MsmcRegs *)CSL_MSMC_CONFIG_REGS; +CSL_GpioRegs * gpGPIO_regs= (CSL_GpioRegs * )CSL_GPIO_REGS; + +CSL_CPINTCRegs* gpCIC0_regs = (CSL_CPINTCRegs*)CSL_CP_INTC_0_REGS; +CSL_CPINTCRegs* gpCIC1_regs = (CSL_CPINTCRegs*)CSL_CP_INTC_1_REGS; +/*The register pointer for the CIC routing events DSP core. +By default, it is CIC0; but for core 4~7 of C6678, it is CIC1*/ +CSL_CPINTCRegs* gpCIC_regs= (CSL_CPINTCRegs*)CSL_CP_INTC_0_REGS; + +CSL_TpccRegs* gpEDMA_CC0_regs = (CSL_TpccRegs*)CSL_EDMA0CC_REGS; +CSL_TpccRegs* gpEDMA_CC1_regs = (CSL_TpccRegs*)CSL_EDMA1CC_REGS; +CSL_TpccRegs* gpEDMA_CC2_regs = (CSL_TpccRegs*)CSL_EDMA2CC_REGS; +CSL_TpccRegs* gpEDMA_CC_regs[3] = { + (CSL_TpccRegs*)CSL_EDMA0CC_REGS, + (CSL_TpccRegs*)CSL_EDMA1CC_REGS, + (CSL_TpccRegs*)CSL_EDMA2CC_REGS +}; + +CSL_TptcRegs * gpEDMA_TC_0_0_regs=(CSL_TptcRegs *) CSL_EDMA0TC0_REGS; +CSL_TptcRegs * gpEDMA_TC_0_1_regs=(CSL_TptcRegs *) CSL_EDMA0TC1_REGS; +CSL_TptcRegs * gpEDMA_TC_1_0_regs=(CSL_TptcRegs *) CSL_EDMA1TC0_REGS; +CSL_TptcRegs * gpEDMA_TC_1_1_regs=(CSL_TptcRegs *) CSL_EDMA1TC1_REGS; +CSL_TptcRegs * gpEDMA_TC_1_2_regs=(CSL_TptcRegs *) CSL_EDMA1TC2_REGS; +CSL_TptcRegs * gpEDMA_TC_1_3_regs=(CSL_TptcRegs *) CSL_EDMA1TC3_REGS; +CSL_TptcRegs * gpEDMA_TC_2_0_regs=(CSL_TptcRegs *) CSL_EDMA2TC0_REGS; +CSL_TptcRegs * gpEDMA_TC_2_1_regs=(CSL_TptcRegs *) CSL_EDMA2TC1_REGS; +CSL_TptcRegs * gpEDMA_TC_2_2_regs=(CSL_TptcRegs *) CSL_EDMA2TC2_REGS; +CSL_TptcRegs * gpEDMA_TC_2_3_regs=(CSL_TptcRegs *) CSL_EDMA2TC3_REGS; + +CSL_TptcRegs * gpEDMA_TC_regs[10]= { + (CSL_TptcRegs *) CSL_EDMA0TC0_REGS, + (CSL_TptcRegs *) CSL_EDMA0TC1_REGS, + (CSL_TptcRegs *) CSL_EDMA1TC0_REGS, + (CSL_TptcRegs *) CSL_EDMA1TC1_REGS, + (CSL_TptcRegs *) CSL_EDMA1TC2_REGS, + (CSL_TptcRegs *) CSL_EDMA1TC3_REGS, + (CSL_TptcRegs *) CSL_EDMA2TC0_REGS, + (CSL_TptcRegs *) CSL_EDMA2TC1_REGS, + (CSL_TptcRegs *) CSL_EDMA2TC2_REGS, + (CSL_TptcRegs *) CSL_EDMA2TC3_REGS +}; + +CSL_TmrPlusRegs * gpTimer0Regs = (CSL_TmrPlusRegs *)CSL_TIMER_0_REGS; +CSL_TmrPlusRegs * gpTimer1Regs = (CSL_TmrPlusRegs *)CSL_TIMER_1_REGS; +CSL_TmrPlusRegs * gpTimer2Regs = (CSL_TmrPlusRegs *)CSL_TIMER_2_REGS; +CSL_TmrPlusRegs * gpTimer3Regs = (CSL_TmrPlusRegs *)CSL_TIMER_3_REGS; +CSL_TmrPlusRegs * gpTimer4Regs = (CSL_TmrPlusRegs *)CSL_TIMER_4_REGS; +CSL_TmrPlusRegs * gpTimer5Regs = (CSL_TmrPlusRegs *)CSL_TIMER_5_REGS; +CSL_TmrPlusRegs * gpTimer6Regs = (CSL_TmrPlusRegs *)CSL_TIMER_6_REGS; +CSL_TmrPlusRegs * gpTimer7Regs = (CSL_TmrPlusRegs *)CSL_TIMER_7_REGS; +CSL_TmrPlusRegs * gpTimer8Regs = (CSL_TmrPlusRegs *)(CSL_TIMER_7_REGS+(CSL_TIMER_7_REGS-CSL_TIMER_6_REGS)); +CSL_TmrPlusRegs * gpTimerRegs[9] = { + (CSL_TmrPlusRegs *)CSL_TIMER_0_REGS, + (CSL_TmrPlusRegs *)CSL_TIMER_1_REGS, + (CSL_TmrPlusRegs *)CSL_TIMER_2_REGS, + (CSL_TmrPlusRegs *)CSL_TIMER_3_REGS, + (CSL_TmrPlusRegs *)CSL_TIMER_4_REGS, + (CSL_TmrPlusRegs *)CSL_TIMER_5_REGS, + (CSL_TmrPlusRegs *)CSL_TIMER_6_REGS, + (CSL_TmrPlusRegs *)CSL_TIMER_7_REGS, + (CSL_TmrPlusRegs *)(CSL_TIMER_7_REGS+(CSL_TIMER_7_REGS-CSL_TIMER_6_REGS)) +}; + +/*MPU for peripherals registers and data space*/ +CSL_MpuRegs * gpMPU0_regs= (CSL_MpuRegs *)CSL_MPU_0_REGS; +CSL_MpuRegs * gpMPU1_regs= (CSL_MpuRegs *)CSL_MPU_1_REGS; +CSL_MpuRegs * gpMPU2_regs= (CSL_MpuRegs *)CSL_MPU_2_REGS; +CSL_MpuRegs * gpMPU3_regs= (CSL_MpuRegs *)CSL_MPU_3_REGS; + +CSL_Emif4fRegs * gpDDR_regs= (CSL_Emif4fRegs *)CSL_DDR3_EMIF_CONFIG_REGS; +unsigned int gDSP_Core_Speed_Hz= 1000000000; //DSP core clock speed in Hz +TDSP_Board_Type gDSP_board_type= UNKNOWN; + +/*----------------------------------------------* + * module-wide global variables * + *----------------------------------------------*/ + +/*----------------------------------------------* + * constants * + *----------------------------------------------*/ + +/*----------------------------------------------* + * macros * + *----------------------------------------------*/ + +/*----------------------------------------------* + * routines' implementations * + *----------------------------------------------*/ + +/***************************************************************************** + Prototype : KeyStone_main_PLL_init + Description : DSP core PLL configuration + DSP core will be configured to run at ref_clock_MHz*multiplier/divisor + Input : float ref_clock_MHz + unsigned int multiplier: 1~4096 + unsigned int divisor: 1~64 + Output : + Return Value : + + History : + 1.Date : 2010-12-12 + Author : Brighton Feng + Modification : Created function + 2.Date : May 19, 2013 + Author : Brighton Feng + Modification : update parameter check; replace constant with macro + +*****************************************************************************/ +void KeyStone_main_PLL_init (float ref_clock_MHz, + unsigned int multiplier, unsigned int divisor) +{ + unsigned int i; + + if(0==divisor) + { + puts("Error: PLL input divider = 0"); + return; + } + + if(64SECCTL & PLLCTL_BYPASS_MASK) + { + /*a. In MAINPLLCTL1, write ENSAT = 1 (for optimal PLL operation) */ + gpBootCfgRegs->CORE_PLL_CTL1 |= PLLCTL1_ENSAT_MASK; /*Set ENSAT bit = 1*/ + + /*b. In PLLCTL, write PLLEN = 0 (bypass enabled in PLL controller mux) */ + gpPLLC_regs->PLLCTL &= ~CSL_PLLC_PLLCTL_PLLEN_MASK; + + /*c. In PLLCTL, write PLLENSRC = 0 (enable PLLEN to control PLL controller mux */ + gpPLLC_regs->PLLCTL &= ~CSL_PLLC_PLLCTL_PLLENSRC_MASK; + + /*d. Wait 4 cycles of the reference clock CLKIN (to make sure the PLL controller */ + /*mux switches properly to the bypass) */ + for(i=0; i< 4; i++) + asm(" nop 5"); + + /*e. In SECCTL, write BYPASS = 1 (bypass enabled in PLL mux) */ + gpPLLC_regs->SECCTL |= PLLCTL_BYPASS_MASK; + + /*f. In PLLCTL, write PLLPWRDN = 1 (power down the PLL) */ + gpPLLC_regs->PLLCTL |= CSL_PLLC_PLLCTL_PLLPWRDN_MASK; //Power down the PLL + + /*g. Wait for at least 5 ��s based on the reference clock CLKIN (PLL power down */ + /*toggling time) */ + for(i=0; i< 1000; i++) + asm(" nop 5"); + + /*h. In PLLCTL, write PLLPWRDN = 0 (power up the PLL) */ + gpPLLC_regs->PLLCTL &= ~CSL_PLLC_PLLCTL_PLLPWRDN_MASK; // Power up PLL + } + else + { + /*a. In PLLCTL, write PLLEN = 0 (bypass enabled in PLL controller mux) */ + gpPLLC_regs->PLLCTL &= (~CSL_PLLC_PLLCTL_PLLEN_MASK); + + /*b. In PLLCTL, write PLLENSRC = 0 (enable PLLEN to control PLL controller mux */ + gpPLLC_regs->PLLCTL &= (~CSL_PLLC_PLLCTL_PLLENSRC_MASK); + + /*c. Wait 4 cycles of the reference clock CLKIN (to make sure the PLL controller */ + /*mux switches properly to the bypass) */ + for(i=0; i< 4*multiplier/divisor; i++) + asm(" nop 5"); + } + + /*4. PLLM is split in two different registers. Program PLLM[5:0] in PLL multiplier */ + /*control register (PLLM) and PLLM[12:6] in MAINPLLCTL0 register */ + /*5. BWADJ is split in two different registers. Program BWADJ[7:0] in */ + /*MAINPLLCTL0 and BWADJ[11:8] in MAINPLLCTL1 register. BWADJ value */ + /*must be set to ((PLLM + 1) >> 1) - 1) */ + /*6. Program PLLD in MAINPLLCTL0 register */ + gpBootCfgRegs->CORE_PLL_CTL0 = ((multiplier-1)<PLLM= (multiplier*2-1)&0x3F; + gpBootCfgRegs->CORE_PLL_CTL1 &= ~PLLCTL1_BWADJ_MASK; + gpBootCfgRegs->CORE_PLL_CTL1 |= (multiplier-1)>>8; /*BWADJ[11:8]*/ + + /*7. In SECCTL, write OD (Output Divide) = 1 (that is divide-by-2) */ + gpPLLC_regs->SECCTL &= ~PLLCTL_OD_MASK; + gpPLLC_regs->SECCTL |= 1<PLLSTAT) & CSL_PLLC_PLLSTAT_GOSTAT_MASK); + + /* Step 8b: Program the RATIO field in PLLDIVn to the desired new divide-down rate. + If RATIO field is changed, the PLL controller will flag the change in the + corresponding bit of DCHANGE*/ + gpPLLC_regs->PLLDIV1_3[3-1] = (3-1) | CSL_PLLC_PLLDIV1_3_DNEN_MASK; //Set PLLDIV3 + gpPLLC_regs->PLLDIV4_16[4-4] = (5-1) | CSL_PLLC_PLLDIV4_16_DNEN_MASK; //Set PLLDIV4 + gpPLLC_regs->PLLDIV4_16[7-4] = (6-1) | CSL_PLLC_PLLDIV4_16_DNEN_MASK; //Set PLLDIV7 + + /* Step 8c: Set GOSET bit in PLLCMD to initiate the GO operation to change the divide + values and align the SYSCLKs as programmed */ + gpPLLC_regs->PLLCMD |= CSL_PLLC_PLLCMD_GOSET_MASK; + + /*Step 8d/e: Read the GOSTAT bit in PLLSTAT to make sure the bit returns to 0 to + indicate that the GO operation has completed */ + while((gpPLLC_regs->PLLSTAT) & CSL_PLLC_PLLSTAT_GOSTAT_MASK); +#endif + + /*9. In PLLCTL , write PLLRST = 1 (PLL reset is asserted)*/ + gpPLLC_regs->PLLCTL |= CSL_PLLC_PLLCTL_PLLRST_MASK; + + /*10. Wait for at least 7 ��s based on the reference clock CLKIN (PLL reset time) */ + for(i=0; i< 2000; i++) + asm(" nop 5"); + + /*11. In PLLCTL, write PLLRST = 0 (PLL reset is released) */ + gpPLLC_regs->PLLCTL &= ~CSL_PLLC_PLLCTL_PLLRST_MASK; + + /*12. Wait for at least 2000 �� CLKIN cycles �� (PLLD + 1) (PLL lock time) */ + for(i=0; i< 400*multiplier; i++) + asm(" nop 5"); + + /*13. In SECCTL, write BYPASS = 0 (enable PLL mux to switch to PLL mode) */ + gpPLLC_regs->SECCTL &= ~PLLCTL_BYPASS_MASK; + + /*14. Set the PLLEN bit in PLLCTL to 1 to enable PLL mode*/ + gpPLLC_regs->PLLCTL |= CSL_PLLC_PLLCTL_PLLEN_MASK; + +} +/***************************************************************************** + Prototype : KeyStone_PLL_init + Description : Config the PLL of PA and DDR + target clock speed will be ref_clock_MHz/inputDivisor*multiplier/outputDivisor + Input : unsigned int inputDivisor + unsigned int multiplier + unsigned int outputDivisor + Output : None + Return Value : 0 for success, other value for error + + History : + 1.Date : May 18, 2013 + Author : Brighton Feng + Modification : Created function + +*****************************************************************************/ +int KeyStone_PLL_init (PLL_ControlRegs * PLL_Regs, unsigned int inputDivisor, + unsigned int multiplier, unsigned int outputDivisor) +{ + if(0==inputDivisor) + { + puts("Error: PLL input divider = 0"); + return 1; + } + + if(64PLL_CTL1 = PLLCTL1_ENSAT_MASK; + + /*2. In PLLCTL0, write BYPASS = 1 (set the PLL in Bypass)*/ + PLL_Regs->PLL_CTL0 |= PLLCTL_BYPASS_MASK; + + /*3. Program PLLM and PLLD in PLLCTL0 register*/ + /*4. Program BWADJ[7:0] in PLLCTL0 and BWADJ[11:8] in PLLCTL1 register. + BWADJ value must be set to ((PLLM + 1) >> 1) �C 1)*/ + PLL_Regs->PLL_CTL0 = ((multiplier/2-1)<PLL_CTL1 &= ~PLLCTL1_BWADJ_MASK; + PLL_Regs->PLL_CTL1 |= (multiplier/2-1)>>8; /*BWADJ[11:8]*/ + + /*5. In PLLCTL1, write PLLRST = 1 (PLL is reset)*/ + PLL_Regs->PLL_CTL1 |= PLLCTL1_PLLRESET_MASK; //Set RESET bit = 1 + + /*6. Wait for at least 7 us based on the reference clock (PLL reset time)*/ + TSC_delay_us(7); + + /*For PASS, In PASSPLLCTL1, write PLLSELECT = 1 + (for selecting the output of PA PLL as the input to PASS)*/ + if(PLL_Regs==(PLL_ControlRegs *)gpBootCfgRegs->PA_PLL_CTL0) + PLL_Regs->PLL_CTL1 |= PLLCTL1_PAPLL_MASK; + + /*7. In PLLCTL1, write PLLRST = 0 (PLL reset is released)*/ + PLL_Regs->PLL_CTL1 &= ~PLLCTL1_PLLRESET_MASK; //Clear RESET bit + + /*8. Wait for at least 500 * REFCLK cycles * (PLLD + 1) (PLL lock time)*/ + TSC_delay_us(500); + + /*9. In PLLCTL0, write BYPASS = 0 (switch to PLL mode)*/ + PLL_Regs->PLL_CTL0 &= ~PLLCTL_BYPASS_MASK ; + + return 0; +} +/***************************************************************************** + Prototype : KeyStone_PASS_PLL_init + Description : Config the PASS PLL + target clock speed will be ref_clock_MHz/divisor*multiplier + Input : float ref_clock_MHz + unsigned int multiplier: 1~4096 + unsigned int divisor: 1~64 + Output : None + Return Value : + + History : + 1.Date : 2013-2-14 + Author : Brighton Feng + Modification : Created function + +*****************************************************************************/ +void KeyStone_PASS_PLL_init (float ref_clock_MHz, + unsigned int multiplier, unsigned int divisor) +{ + //output divisor for PASS PLL should be 2 + if(0==KeyStone_PLL_init((PLL_ControlRegs *)&gpBootCfgRegs->PA_PLL_CTL0, + divisor, multiplier*2, 2)) + { + printf("Initialize PASS PLL clock = %.2fMHz/%dx%d = %.3fMHz\n", + ref_clock_MHz, divisor, multiplier, + ref_clock_MHz*multiplier/divisor); + } +} + +/***************************************************************************** + Prototype : KeyStone_DDR_PLL_init + Description : Config the DDR PLL + target clock speed will be ref_clock_MHz/divisor*multiplier + Input : float ref_clock_MHz + unsigned int multiplier: 1~4096 + unsigned int divisor: 1~64 + Output : None + Return Value : + + History : + 1.Date : 2013-8-18 + Author : Brighton Feng + Modification : Created function + +*****************************************************************************/ +void KeyStone_DDR_PLL_init (float ref_clock_MHz, + unsigned int multiplier, unsigned int divisor) +{ + //output divisor for DDR PLL should be 2 + if(0==KeyStone_PLL_init((PLL_ControlRegs *)&gpBootCfgRegs->DDR3_PLL_CTL0, + divisor, multiplier, 2)) + { + printf("Initialize DDR speed = %.2fMHzx/%dx%d = %.3fMTS\n", + ref_clock_MHz, divisor, multiplier, + ref_clock_MHz*multiplier/divisor); + } +} + +/*===============================TSC===================================*/ +unsigned int cycle_measure_overhead=50; +/***************************************************************************** + Prototype : calc_cycle_measure_overhead + Description : calclucate the cycles measurement overhead + Input : None + Output : None + Return Value : + + History : + 1.Date : 2010/12/12 + Author : Brighton Feng + Modification : Created function + +*****************************************************************************/ +void calc_cycle_measure_overhead() +{ + unsigned int cycle_cold, cycle_warm; + cycle_cold= TSCL; + cycle_cold = TSC_getDelay(cycle_cold); + cycle_warm= TSCL; + cycle_warm = TSC_getDelay(cycle_warm); + cycle_measure_overhead = (cycle_cold + cycle_warm)/2; +} + +/***************************************************************************** + Prototype : TSC_init + Description : Initialize Time stamp counter to measure cycles + Input : None + Output : None + Return Value : + + History : + 1.Date : 2010/12/12 + Author : Brighton Feng + Modification : Created function + +*****************************************************************************/ +void TSC_init() +{ + TSCL = 0; /* Enable the TSC */ + calc_cycle_measure_overhead(); +} + +/***************************************************************************** + Prototype : TSC_delay_ms + Description : Implement the delay function in millisecond + Input : Uint32 ms + Output : None + Return Value : + + History : + 1.Date : 2010/12/12 + Author : Brighton Feng + Modification : Created function + +*****************************************************************************/ +void TSC_delay_ms(Uint32 ms) +{ + volatile unsigned long long startTSC, currentTSC; + unsigned long long delay_cycles; + Uint32 tscl, tsch; + + tscl= TSCL; + tsch= TSCH; + startTSC= _itoll(tsch,tscl); + + delay_cycles= ((unsigned long long)ms*gDSP_Core_Speed_Hz/1000); + + do + { + tscl= TSCL; + tsch= TSCH; + currentTSC= _itoll(tsch,tscl); + } + while((currentTSC-startTSC)TGCR) + { + gpTimerRegs[timer_num]->TGCR= 0; + gpTimerRegs[timer_num]->TCR= 0; + } +} + + /***************************************************************************** + Prototype : Timer64_Init + Description : Initialize a 64-bit timer + Input : Timer64_Config * tmrCfg + Output : None + Return Value : + + History : + 1.Date : 2010/12/12 + Author : Brighton Feng + Modification : Created function + +*****************************************************************************/ +void Timer64_Init(Timer64_Config * tmrCfg) +{ + Reset_Timer(tmrCfg->timer_num); + + gpTimerRegs[tmrCfg->timer_num]->CNTLO= 0; + gpTimerRegs[tmrCfg->timer_num]->CNTHI= 0; + + /*please note, in clock mode, two timer periods generate a clock, + one timer period output high voltage level, the other timer period + output low voltage level, so, the timer period should be half to the + desired output clock period*/ + if(TIMER_PERIODIC_CLOCK==tmrCfg->timerMode) + tmrCfg->period= tmrCfg->period/2; + + /*the value written into period register is the expected value minus one*/ + gpTimerRegs[tmrCfg->timer_num]->PRDLO= _loll(tmrCfg->period-1); + gpTimerRegs[tmrCfg->timer_num]->PRDHI= _hill(tmrCfg->period-1); + if(tmrCfg->reload_period>1) + { + gpTimerRegs[tmrCfg->timer_num]->RELLO= _loll(tmrCfg->reload_period-1); + gpTimerRegs[tmrCfg->timer_num]->RELHI= _hill(tmrCfg->reload_period-1); + } + + if(TIMER_WATCH_DOG==tmrCfg->timerMode) + { + gpTimerRegs[tmrCfg->timer_num]->TGCR= + /*Select watch-dog mode*/ + (CSL_TMR_TIMMODE_WDT<timerMode) + { + gpTimerRegs[tmrCfg->timer_num]->TGCR= TMR_TGCR_PLUSEN_MASK + /*for plus featuers, dual 32-bit unchained timer mode should be used*/ + |(CSL_TMR_TIMMODE_DUAL_UNCHAINED<timer_num]->INTCTL_STAT= TMR_INTCTLSTAT_EN_ALL_CLR_ALL; + } + else + { + gpTimerRegs[tmrCfg->timer_num]->TGCR= + /*Select 64-bit general timer mode*/ + (CSL_TMR_TIMMODE_GPT<timer_num]->EMUMGT_CLKSPD = (gpTimerRegs[tmrCfg->timer_num]->EMUMGT_CLKSPD& + ~(CSL_TMR_EMUMGT_CLKSPD_FREE_MASK|CSL_TMR_EMUMGT_CLKSPD_SOFT_MASK)); + + if(TIMER_WATCH_DOG==tmrCfg->timerMode) + { + /*enable watchdog timer*/ + gpTimerRegs[tmrCfg->timer_num]->WDTCR = CSL_TMR_WDTCR_WDEN_MASK + |(CSL_TMR_WDTCR_WDKEY_CMD1<timer_num]->TCR= + (CSL_TMR_CLOCK_INP_NOGATE<pulseWidth<timer_num]->WDTCR = CSL_TMR_WDTCR_WDEN_MASK + |(CSL_TMR_WDTCR_WDKEY_CMD2<timerMode) + { + gpTimerRegs[tmrCfg->timer_num]->TCR= + (CSL_TMR_CLOCK_INP_NOGATE<pulseWidth<timerMode) + { + gpTimerRegs[tmrCfg->timer_num]->TCR= + (CSL_TMR_CLOCK_INP_NOGATE<pulseWidth<timerMode) + { + gpTimerRegs[tmrCfg->timer_num]->TCR= + (CSL_TMR_CLOCK_INP_NOGATE<pulseWidth<timer_num]->TCR= + (CSL_TMR_CLOCK_INP_NOGATE<pulseWidth<WDTCR = + (CSL_TMR_WDTCR_WDKEY_CMD1<WDTCR = + (CSL_TMR_WDTCR_WDKEY_CMD2<0x3FFFFFFF) + { + printf("Enable power domain %d timeout!\n", pwrDmnNum); + return -2; + } + } + } + + /* Enable the clocks too*/ + CSL_PSC_setModuleNextState (moduleNum, PSC_MODSTATE_ENABLE); + + /* Start the state transition */ + CSL_PSC_startStateTransition (pwrDmnNum); + + /* Wait until the state transition process is completed. */ + while (!CSL_PSC_isStateTransitionDone (pwrDmnNum)) + { + if(TSC_count_cycle_from(uiStartTSC)>0x3FFFFFFF) + { + printf("Enable clock domain %d timeout!\n", moduleNum); + return -2; + } + } + + /* Return PSC status */ + if ((CSL_PSC_getPowerDomainState(pwrDmnNum) == PSC_PDSTATE_ON) && + (CSL_PSC_getModuleState (moduleNum) == PSC_MODSTATE_ENABLE)) + { + /*Ready for use */ + return 0; + } + else + { + /*Return error */ + return -1; + } +} +/***************************************************************************** + Prototype : KeyStone_disable_PSC_module + Description : Disable the PSC module in KeyStone device + Input : Uint32 pwrDmnNum + Uint32 moduleNum + Output : None + Return Value : + + History : + 1.Date : 2010/2/12 + Author : Brighton Feng + Modification : Created function + +*****************************************************************************/ +Int32 KeyStone_disable_PSC_module (Uint32 pwrDmnNum, Uint32 moduleNum) +{ + Uint32 uiStartTSC= TSCL; + + /* disable the clocks*/ + CSL_PSC_setModuleNextState (moduleNum, PSC_MODSTATE_SWRSTDISABLE); + + /* Start the state transition */ + CSL_PSC_startStateTransition (pwrDmnNum); + + /* Wait until the state transition process is completed. */ + while (!CSL_PSC_isStateTransitionDone (pwrDmnNum)) + { + if(TSC_count_cycle_from(uiStartTSC)>0x3FFFFFFF) + { + printf("Disable clock domain %d timeout!\n", moduleNum); + return -2; + } + } + + /* Return PSC status */ + if (CSL_PSC_getModuleState (moduleNum) == PSC_MODSTATE_SWRSTDISABLE) + { + /*Ready for use */ + return 0; + } + else + { + /*Return error */ + return -1; + } + +} +/***************************************************************************** + Prototype : KeyStone_disable_PSC_Power_Domain + Description : Disable the PSC power domain + Input : Uint32 pwrDmnNum + Output : None + Return Value : + + History : + 1.Date : 2010/12/12 + Author : Brighton Feng + Modification : Created function + +*****************************************************************************/ +Int32 KeyStone_disable_PSC_Power_Domain (Uint32 pwrDmnNum) +{ + Uint32 uiStartTSC= TSCL; + + /* Set Power domain to OFF */ + CSL_PSC_disablePowerDomain (pwrDmnNum); + + /* Start the state transition */ + CSL_PSC_startStateTransition (pwrDmnNum); + + /* Wait until the state transition process is completed. */ + while (!CSL_PSC_isStateTransitionDone (pwrDmnNum)) + { + if(TSC_count_cycle_from(uiStartTSC)>0x3FFFFFFF) + { + printf("Disable power domain %d timeout!\n", pwrDmnNum); + return -2; + } + } + + /* Return PSC status */ + if (CSL_PSC_getPowerDomainState(pwrDmnNum) == PSC_PDSTATE_OFF) + { + /*Ready for use */ + return 0; + } + else + { + /*Return error */ + return -1; + } + +} + +/*============================EDMA=====================================*/ + /***************************************************************************** + Prototype : EDMA_channel_TC_cfg + Description : Setup uiChannel of an EDMA to use uiTC + Input : Uint32 uiCC + Uint32 uiChannel + Uint32 uiTC + Output : None + Return Value : + + History : + 1.Date : 2010/12/12 + Author : Brighton Feng + Modification : Created function + +*****************************************************************************/ +void EDMA_channel_TC_cfg (Uint32 uiCC, + Uint32 uiChannel, Uint32 uiTC) +{ + gpEDMA_CC_regs[uiCC]->TPCC_DMAQNUM[uiChannel/8] = + (gpEDMA_CC_regs[uiCC]->TPCC_DMAQNUM[uiChannel/8]&(~(0xF<<((uiChannel&7)*4)))) + |(uiTC<<((uiChannel&7)*4)); +} +/***************************************************************************** + Prototype : EDMA_TC_priority_cfg + Description : Setup uiChannel of an EDMA TC priority + Input : Uint32 uiCC + Uint32 uiPri + Uint32 uiTC + Output : None + Return Value : + + History : + 1.Date : 2010/12/12 + Author : Brighton Feng + Modification : Created function + +*****************************************************************************/ +void EDMA_TC_priority_cfg(Uint32 uiCC, + Uint32 uiPri, Uint32 uiTC) +{ + gpEDMA_CC_regs[uiCC]->TPCC_QUEPRI= + (gpEDMA_CC_regs[uiCC]->TPCC_QUEPRI&(~(0xF<<((uiTC&3)*4)))) + |(uiPri<<((uiTC&3)*4)); +} +/***************************************************************************** + Prototype : EDMA_init + Description : Initialize all EDMA registers and clear the event + Input : None + Output : None + Return Value : + + History : + 1.Date : 2010/12/12 + Author : Brighton Feng + Modification : Created function + +*****************************************************************************/ +void EDMA_init () +{ + int i; + unsigned int * uipPaRAM; + + /*clear PaRAM*/ + uipPaRAM= (unsigned int *)&(gpEDMA_CC0_regs->PARAMSET[0]); + for(i=0; i<8*CSL_EDMA3_TPCC0_NUM_PARAMSETS; i++) + *uipPaRAM++=0; + + uipPaRAM= (unsigned int *)&(gpEDMA_CC1_regs->PARAMSET[0]); + for(i=0; i<8*CSL_EDMA3_TPCC1_NUM_PARAMSETS; i++) + *uipPaRAM++=0; + + uipPaRAM= (unsigned int *)&(gpEDMA_CC2_regs->PARAMSET[0]); + for(i=0; i<8*CSL_EDMA3_TPCC2_NUM_PARAMSETS; i++) + *uipPaRAM++=0; + + /*Assign PaRAM for different channels*/ + for(i=0; iTPCC_DCHMAP[i] = i<< CSL_TPCC_TPCC_DCHMAP0_PAENTRY_SHIFT; + + for(i=0; iTPCC_DCHMAP[i] = i<< CSL_TPCC_TPCC_DCHMAP0_PAENTRY_SHIFT; + + for(i=0; iTPCC_DCHMAP[i] = i<< CSL_TPCC_TPCC_DCHMAP0_PAENTRY_SHIFT; + + /*Assign TC/Queue for different channels*/ + gpEDMA_CC0_regs->TPCC_DMAQNUM[0]= 0x10101010; + gpEDMA_CC0_regs->TPCC_DMAQNUM[1]= 0x10101010; + + gpEDMA_CC1_regs->TPCC_DMAQNUM[0]= 0x32103210; + gpEDMA_CC1_regs->TPCC_DMAQNUM[1]= 0x32103210; + gpEDMA_CC1_regs->TPCC_DMAQNUM[2]= 0x32103210; + gpEDMA_CC1_regs->TPCC_DMAQNUM[3]= 0x32103210; + gpEDMA_CC1_regs->TPCC_DMAQNUM[4]= 0x32103210; + gpEDMA_CC1_regs->TPCC_DMAQNUM[5]= 0x32103210; + gpEDMA_CC1_regs->TPCC_DMAQNUM[6]= 0x32103210; + gpEDMA_CC1_regs->TPCC_DMAQNUM[7]= 0x32103210; + + gpEDMA_CC2_regs->TPCC_DMAQNUM[0]= 0x32103210; + gpEDMA_CC2_regs->TPCC_DMAQNUM[1]= 0x32103210; + gpEDMA_CC2_regs->TPCC_DMAQNUM[2]= 0x32103210; + gpEDMA_CC2_regs->TPCC_DMAQNUM[3]= 0x32103210; + gpEDMA_CC2_regs->TPCC_DMAQNUM[4]= 0x32103210; + gpEDMA_CC2_regs->TPCC_DMAQNUM[5]= 0x32103210; + gpEDMA_CC2_regs->TPCC_DMAQNUM[6]= 0x32103210; + gpEDMA_CC2_regs->TPCC_DMAQNUM[7]= 0x32103210; + + /*clear any events and status*/ + gpEDMA_CC0_regs->TPCC_ECR= 0xFFFF; + gpEDMA_CC0_regs->TPCC_EECR= 0xFFFF; + gpEDMA_CC0_regs->TPCC_ICR= 0xFFFF; + gpEDMA_CC0_regs->TPCC_IECR= 0xFFFF; + gpEDMA_CC0_regs->TPCC_EMCR= 0xFFFF; + gpEDMA_CC0_regs->TPCC_QEMCR= 0xFFFF; + gpEDMA_CC0_regs->TPCC_CCERRCLR= 0xFFFF; + gpEDMA_CC0_regs->TPCC_SECR= 0xFFFF; + + gpEDMA_CC1_regs->TPCC_ECR= 0xFFFFFFFF; + gpEDMA_CC1_regs->TPCC_ECRH= 0xFFFFFFFF; + gpEDMA_CC1_regs->TPCC_EECR= 0xFFFFFFFF; + gpEDMA_CC1_regs->TPCC_EECRH= 0xFFFFFFFF; + gpEDMA_CC1_regs->TPCC_ICR= 0xFFFFFFFF; + gpEDMA_CC1_regs->TPCC_ICRH= 0xFFFFFFFF; + gpEDMA_CC1_regs->TPCC_IECR= 0xFFFFFFFF; + gpEDMA_CC1_regs->TPCC_IECRH= 0xFFFFFFFF; + gpEDMA_CC1_regs->TPCC_EMCR= 0xFFFFFFFF; + gpEDMA_CC1_regs->TPCC_EMCRH= 0xFFFFFFFF; + gpEDMA_CC1_regs->TPCC_QEMCR= 0xFFFFFFFF; + gpEDMA_CC1_regs->TPCC_CCERRCLR= 0xFFFF; + gpEDMA_CC1_regs->TPCC_SECR= 0xFFFFFFFF; + gpEDMA_CC1_regs->TPCC_SECRH= 0xFFFFFFFF; + + gpEDMA_CC2_regs->TPCC_ECR= 0xFFFFFFFF; + gpEDMA_CC2_regs->TPCC_ECRH= 0xFFFFFFFF; + gpEDMA_CC2_regs->TPCC_EECR= 0xFFFFFFFF; + gpEDMA_CC2_regs->TPCC_EECRH= 0xFFFFFFFF; + gpEDMA_CC2_regs->TPCC_ICR= 0xFFFFFFFF; + gpEDMA_CC2_regs->TPCC_ICRH= 0xFFFFFFFF; + gpEDMA_CC2_regs->TPCC_IECR= 0xFFFFFFFF; + gpEDMA_CC2_regs->TPCC_IECRH= 0xFFFFFFFF; + gpEDMA_CC2_regs->TPCC_EMCR= 0xFFFFFFFF; + gpEDMA_CC2_regs->TPCC_EMCRH= 0xFFFFFFFF; + gpEDMA_CC2_regs->TPCC_QEMCR= 0xFFFFFFFF; + gpEDMA_CC2_regs->TPCC_CCERRCLR= 0xFFFF; + gpEDMA_CC2_regs->TPCC_SECR= 0xFFFFFFFF; + gpEDMA_CC2_regs->TPCC_SECRH= 0xFFFFFFFF; + + for(i=0; iTPTC_ERRCLR= 0xF; + + //enable error interrupt + gpEDMA_TC_regs[i]->TPTC_ERREN= + (1<TPCC_EESR= 1<<(uiChannel); + } + else + { + //enable the EDMA channel + gpEDMA_CC_regs[uiCC]->TPCC_EESRH= 1<<(uiChannel-32); + } +} + +void EDMA_event_disable(Uint32 uiCC, Uint32 uiChannel) +{ + if(uiChannel<32) + { + //disable the EDMA channel + gpEDMA_CC_regs[uiCC]->TPCC_EECR= 1<<(uiChannel); + } + else + { + //disable the EDMA channel + gpEDMA_CC_regs[uiCC]->TPCC_EECRH= 1<<(uiChannel-32); + } +} + +void EDMA_interrupt_enable(Uint32 uiCC, Uint32 uiIntNum) +{ + if(uiIntNum<32) + { + //enable the EDMA channel interrupt + gpEDMA_CC_regs[uiCC]->TPCC_IESR= 1<<(uiIntNum); + } + else + { + //enable the EDMA channel interrupt + gpEDMA_CC_regs[uiCC]->TPCC_IESRH= 1<<(uiIntNum-32); + } +} + +void EDMA_interrupt_disable(Uint32 uiCC, Uint32 uiIntNum) +{ + if(uiIntNum<32) + { + //disable the EDMA channel interrupt + gpEDMA_CC_regs[uiCC]->TPCC_IECR= 1<<(uiIntNum); + } + else + { + //disable the EDMA channel interrupt + gpEDMA_CC_regs[uiCC]->TPCC_IECRH= 1<<(uiIntNum-32); + } +} + +/***************************************************************************** + Prototype : EDMA_wait + Description : wait the pending EDMA complete + Input : EDMA_CC_Channel_Num CC_channel + Output : None + Return Value : + + History : + 1.Date : 2012/10/30 + Author : Brighton Feng + Modification : Created function + +*****************************************************************************/ +void EDMA_wait(EDMA_CC_Channel_Num CC_channel) +{ + CSL_TpccRegs* EDMACCRegs; + unsigned int uiChannel; + volatile Uint32 * TPCC_IPR; + volatile Uint32 * TPCC_ICR; + + EDMACCRegs= gpEDMA_CC_regs[CC_channel>>16]; + uiChannel = CC_channel&0xFF; + + if(uiChannel<32) + { + TPCC_IPR= &EDMACCRegs->TPCC_IPR; + TPCC_ICR= &EDMACCRegs->TPCC_ICR; + } + else + { + TPCC_IPR= &EDMACCRegs->TPCC_IPRH; + TPCC_ICR= &EDMACCRegs->TPCC_ICRH; + uiChannel -= 32; + } + + /*wait for completion*/ + while(0==((*TPCC_IPR)&(1<<(uiChannel)))); + + /*clear completion flag*/ + (*TPCC_ICR)= 1<<(uiChannel); +} + +/***************************************************************************** + Prototype : EDMA_Copy + Description : EDMA copy function with manual trigger + Input : unsigned int srcAddr + unsigned int dstAddr + unsigned int byteCount, <64KB + EDMA_CC_Channel_Num CC_channel + DMA_Wait wait + Output : None + Return Value : + + History : + 1.Date : 2012/10/30 + Author : Brighton Feng + Modification : Created function + +*****************************************************************************/ +void EDMA_copy(unsigned int srcAddr, unsigned int dstAddr, + unsigned int byteCount, EDMA_CC_Channel_Num CC_channel, DMA_Wait wait) +{ + CSL_TpccRegs* EDMACCRegs; + unsigned int uiChannel; + volatile Uint32 * TPCC_ESR; + volatile Uint32 * TPCC_IPR; + volatile Uint32 * TPCC_ICR; + + EDMACCRegs= gpEDMA_CC_regs[CC_channel>>16]; + uiChannel = CC_channel&0xFF; + + EDMACCRegs->PARAMSET[uiChannel].OPT= + CSL_EDMA3_OPT_MAKE(CSL_EDMA3_ITCCH_DIS, + CSL_EDMA3_TCCH_DIS, + CSL_EDMA3_ITCINT_DIS, + CSL_EDMA3_TCINT_EN, + uiChannel, + CSL_EDMA3_TCC_NORMAL, + CSL_EDMA3_FIFOWIDTH_NONE, + CSL_EDMA3_STATIC_DIS, + CSL_EDMA3_SYNC_A, + CSL_EDMA3_ADDRMODE_INCR, + CSL_EDMA3_ADDRMODE_INCR); + EDMACCRegs->PARAMSET[uiChannel].SRC= GLOBAL_ADDR(srcAddr); + EDMACCRegs->PARAMSET[uiChannel].A_B_CNT=CSL_EDMA3_CNT_MAKE(byteCount&0xFFFF, 1); + EDMACCRegs->PARAMSET[uiChannel].DST= GLOBAL_ADDR(dstAddr); + EDMACCRegs->PARAMSET[uiChannel].SRC_DST_BIDX= 0; + EDMACCRegs->PARAMSET[uiChannel].LINK_BCNTRLD= CSL_EDMA3_LINKBCNTRLD_MAKE(0xFFFF, 1); + EDMACCRegs->PARAMSET[uiChannel].SRC_DST_CIDX= 0; + EDMACCRegs->PARAMSET[uiChannel].CCNT= 1; + + if(uiChannel<32) + { + TPCC_ESR= &EDMACCRegs->TPCC_ESR; + TPCC_IPR= &EDMACCRegs->TPCC_IPR; + TPCC_ICR= &EDMACCRegs->TPCC_ICR; + } + else + { + TPCC_ESR= &EDMACCRegs->TPCC_ESRH; + TPCC_IPR= &EDMACCRegs->TPCC_IPRH; + TPCC_ICR= &EDMACCRegs->TPCC_ICRH; + uiChannel -= 32; + } + + /*Manually trigger the EDMA*/ + (*TPCC_ESR)= 1<<(uiChannel); + + if(wait) + { + /*wait for completion*/ + while(0==((*TPCC_IPR)&(1<<(uiChannel)))); + + /*clear completion flag*/ + (*TPCC_ICR)= 1<<(uiChannel); + } +} + +/***************************************************************************** + Prototype : EDMA_fill + Description : EDMA fill function with manual trigger + Input : unsigned int address, must align to 8 bytes boundary + unsigned long long data + unsigned int byteCount, must be multiple of 8 + EDMA_CC_Channel_Num CC_channel + Output : None + Return Value : + + History : + 1.Date : 2013/8/11 + Author : Brighton Feng + Modification : Created function + +*****************************************************************************/ +void EDMA_fill(unsigned int address, unsigned long long data, + unsigned int byteCount, EDMA_CC_Channel_Num CC_channel) +{ + int i; + CSL_TpccRegs* EDMACCRegs; + unsigned int uiChannel, uiChannelShift, uiBCNT; + volatile Uint32 * TPCC_ESR; + volatile Uint32 * TPCC_IPR; + volatile Uint32 * TPCC_ICR; + unsigned long long tempBuf[128/8]; + Uint32 tempBufSize=128, headerSize, tailSize; + + if(tempBufSize>byteCount) + tempBufSize=byteCount; + + for(i=0; i< tempBufSize/8; i++) + tempBuf[i]= data; + + /*split the transfer into 3 sections at 128 byte boundary*/ + if(address&127) //header address not start on 128 byte boundary + { + headerSize= 128- (address&127); + if(headerSize>byteCount) + headerSize=byteCount; + EDMA_copy((Uint32)tempBuf, address, headerSize, CC_channel, DMA_WAIT); + address+= headerSize; + byteCount-= headerSize; + } + + if(byteCount&&((address+byteCount)&127))//tail address not start on 128 byte boundary + { + tailSize= (address+byteCount)&127; + EDMA_copy((Uint32)tempBuf, address+byteCount-tailSize, tailSize, CC_channel, DMA_WAIT); + byteCount-= tailSize; + } + + EDMACCRegs= gpEDMA_CC_regs[CC_channel>>16]; + uiChannel = CC_channel&0xFF; + if(uiChannel<32) + { + TPCC_ESR= &EDMACCRegs->TPCC_ESR; + TPCC_IPR= &EDMACCRegs->TPCC_IPR; + TPCC_ICR= &EDMACCRegs->TPCC_ICR; + uiChannelShift= uiChannel; + } + else + { + TPCC_ESR= &EDMACCRegs->TPCC_ESRH; + TPCC_IPR= &EDMACCRegs->TPCC_IPRH; + TPCC_ICR= &EDMACCRegs->TPCC_ICRH; + uiChannelShift= uiChannel - 32; + } + + EDMACCRegs->PARAMSET[uiChannel].OPT= + CSL_EDMA3_OPT_MAKE(CSL_EDMA3_ITCCH_DIS, + CSL_EDMA3_TCCH_DIS, + CSL_EDMA3_ITCINT_DIS, + CSL_EDMA3_TCINT_EN, + uiChannel, + CSL_EDMA3_TCC_NORMAL, + CSL_EDMA3_FIFOWIDTH_NONE, + CSL_EDMA3_STATIC_EN, //keep PARAM unchanged + CSL_EDMA3_SYNC_AB, + CSL_EDMA3_ADDRMODE_INCR, + CSL_EDMA3_ADDRMODE_INCR); + EDMACCRegs->PARAMSET[uiChannel].SRC= GLOBAL_ADDR(tempBuf); + EDMACCRegs->PARAMSET[uiChannel].SRC_DST_BIDX= CSL_EDMA3_BIDX_MAKE(0, 128); + EDMACCRegs->PARAMSET[uiChannel].LINK_BCNTRLD= CSL_EDMA3_LINKBCNTRLD_MAKE(0xFFFF, 0); + EDMACCRegs->PARAMSET[uiChannel].SRC_DST_CIDX= 0; + EDMACCRegs->PARAMSET[uiChannel].CCNT= 1; + + while(byteCount) //the reminding must be multiple of 128 bytes + { + uiBCNT= byteCount/128; + if(uiBCNT>65535) + uiBCNT= 65535; + + EDMACCRegs->PARAMSET[uiChannel].A_B_CNT= CSL_EDMA3_CNT_MAKE(128, uiBCNT); + EDMACCRegs->PARAMSET[uiChannel].DST= GLOBAL_ADDR(address); + + /*Manually trigger the EDMA*/ + (*TPCC_ESR)= 1<<(uiChannelShift); + + /*wait for completion*/ + while(0==((*TPCC_IPR)&(1<<(uiChannelShift)))); + + /*clear completion flag*/ + (*TPCC_ICR)= 1<<(uiChannelShift); + + byteCount -= uiBCNT*128; + address += uiBCNT*128; + } +} + +/***************************************************************************** + Prototype : IDMA_wait + Description : wait the pending IDMA complete + Input : None + Output : None + Return Value : + + History : + 1.Date : 2012/10/28 + Author : Brighton Feng + Modification : Created function + +*****************************************************************************/ +void IDMA_wait() +{ + /* Wait until copying is completed */ + while (gpCGEM_regs->IDMA1_STAT); +} +/***************************************************************************** + Prototype : IDMA_copy + Description : implement the data copy via IDMA + Input : unsigned int srcAddr + unsigned int dstAddr + unsigned int byteCount, <64KB + IDMA_Wait wait + Output : None + Return Value : + + History : + 1.Date : 2012/10/28 + Author : Brigthon + Modification : Created function + +*****************************************************************************/ +void IDMA_copy(unsigned int srcAddr, unsigned int dstAddr, + unsigned int byteCount, DMA_Wait wait) +{ + gpCGEM_regs->IDMA1_SOURCE= srcAddr; + gpCGEM_regs->IDMA1_DEST= dstAddr; + gpCGEM_regs->IDMA1_COUNT= byteCount&0xFFFC; + + if(wait) + { + /* Wait until copying is completed */ + while (gpCGEM_regs->IDMA1_STAT); + } +} +/***************************************************************************** + Prototype : EDMA_CC_error_handler + Description : Edma channel controller error processing + Input : Uint32 edmaNum, EDMA module number (0~2) + Output : None + Return Value : + + History : + 1.Date : 2012/11/7 + Author : Brighton Feng + Modification : Created function + +*****************************************************************************/ +void EDMA_CC_error_handler(Uint32 edmaNum) +{ + int i; + CSL_TpccRegs* EDMACCRegs= gpEDMA_CC_regs[edmaNum]; + Uint32 EMR, EMRH= 0, QEMR, CCERR; + + //read error status + EMR= EDMACCRegs->TPCC_EMR; + QEMR= EDMACCRegs->TPCC_QEMR; + CCERR= EDMACCRegs->TPCC_CCERR; + exception_record.status.ext_sts.info.edma.CC_info.EMR= EMR; + exception_record.status.ext_sts.info.edma.CC_info.QEMR= QEMR; + exception_record.status.ext_sts.info.edma.CC_info.CCERR= CCERR; + + //clear error status + EDMACCRegs->TPCC_EMCR= EMR; + EDMACCRegs->TPCC_QEMCR= QEMR; + EDMACCRegs->TPCC_CCERRCLR= CCERR; + + //channel 32~63 for EDMA CC1 and CC2 + if(0TPCC_EMRH; + exception_record.status.ext_sts.info.edma.CC_info.EMRH= EMRH; + + //clear error status + EDMACCRegs->TPCC_EMCRH= EMRH; + } + + for(i=0; i<32; i++) + { + if((EMR>>i)&1) + printf(" EDMA Channel %d event missed.\n", i); + if((EMRH>>i)&1) + printf(" EDMA Channel %d event missed.\n", i+32); + } + + for(i=0; i<8; i++) + { + if((QEMR>>i)&1) + printf(" QDMA Channel %d event missed.\n", i); + } + + for(i=0; i<4; i++) + { + if((CCERR>>i)&1) + printf(" Queue %d Watermark/threshold has been exceeded.\n", i); + } + + if(CCERR&CSL_TPCC_TPCC_CCERR_TCCERR_MASK) + puts(" Total number of allowed TCCs has been reached."); + +} +/***************************************************************************** + Prototype : EDMA_TC_error_handler + Description : Edma transfer controller error processing + Input : CSL_TptcRegs * edmaTCRegs + Output : None + Return Value : + + History : + 1.Date : 2012/11/7 + Author : Brighton Feng + Modification : Created function + +*****************************************************************************/ +void EDMA_TC_error_handler(CSL_TptcRegs * edmaTCRegs) +{ + Uint32 ERRSTAT, ERRDET, STAT; + + //read error status + ERRSTAT= edmaTCRegs->TPTC_ERRSTAT; + ERRDET= edmaTCRegs->TPTC_ERRDET; + exception_record.status.ext_sts.info.edma.TC_info.ERRSTAT=ERRSTAT ; + exception_record.status.ext_sts.info.edma.TC_info.ERRDET= ERRDET; + + //clear error + edmaTCRegs->TPTC_ERRCLR= ERRSTAT; + + if(ERRSTAT&CSL_TPTC_TPTC_ERRSTAT_MMRAERR_MASK) + puts(" User attempted to read or write to an invalid address in configuration memory map."); + if(ERRSTAT&CSL_TPTC_TPTC_ERRSTAT_TRERR_MASK) + puts(" TR detected that violates constant addressing mode transfer (SAM or DAM is set) alignment rules or has ACNT or BCNT== 0."); + if(ERRSTAT&CSL_TPTC_TPTC_ERRSTAT_BUSERR_MASK) + { + puts(" EDMA3TC has detected an error at source or destination address."); + + STAT= ERRDET&CSL_TPTC_TPTC_ERRDET_STAT_MASK; + + if(STAT>=8) + printf(" write error (%d). ",STAT); + else if(STAT>=1) + printf(" read error (%d). ",STAT); + else + printf(" no error!?"); + + printf("TCC= %d. TCINTEN= %d. TCCHEN= %d\n", + (ERRDET&CSL_TPTC_TPTC_ERRDET_TCC_MASK)>>CSL_TPTC_TPTC_ERRDET_TCC_SHIFT, + (ERRDET&CSL_TPTC_TPTC_ERRDET_TCINTEN_MASK)>>CSL_TPTC_TPTC_ERRDET_TCINTEN_SHIFT, + (ERRDET&CSL_TPTC_TPTC_ERRDET_TCCHEN_MASK)>>CSL_TPTC_TPTC_ERRDET_TCCHEN_SHIFT); + } + +} +/***************************************************************************** + Prototype : EDMA_error_handler + Description : EDMA error processing function + Input : Uint32 edmaNum + Uint32 errorFlag + error flag bit fields are defined as below + (follow the sequence in CIC) + 0 EDMACC_ERRINT EDMA3CC error interrupt + 2 EDMATC_ERRINT0 EDMA3TC0 error interrupt + 3 EDMATC_ERRINT1 EDMA3TC1 error interrupt + 4 EDMATC_ERRINT2 EDMA3TC2 error interrupt + 5 EDMATC_ERRINT3 EDMA3TC3 error interrupt + Output : None + Return Value : + + History : + 1.Date : 2012/10/28 + Author : Brighton Feng + Modification : Created function + +*****************************************************************************/ +void EDMA_error_handler(Uint32 edmaNum, Uint32 errorFlag) +{ + int i; + + printf(" EDMA module %d error\n", edmaNum); + if(errorFlag&1) + EDMA_CC_error_handler(edmaNum); + + errorFlag >>= 2; + + for(i=0; i<4; i++) + { + if(errorFlag&(1<MPLKCMD = (1<MPLK[i] = mem_prot_key[i]; + } + + /*3. Write a 1 to the LOCK field of the MPLKCMD register. This engages the lock.*/ + gpCGEM_regs->MPLKCMD = (1<MPLKSTAT&CSL_CGEM_MPLKSTAT_LK_MASK)); +} + +/***************************************************************************** + Prototype : unlock_mem_prot_regs + Description : unlock memory protection registers + Input : None + Output : None + Return Value : + + History : + 1.Date : 2010/12/12 + Author : Brighton Feng + Modification : Created function + +*****************************************************************************/ +#pragma CODE_SECTION (unlock_mem_prot_regs, ".text:Core_MPAX") +void unlock_mem_prot_regs() +{ + int i; + + /*1. Write a 1 to the KEYR field in the MPLKCMD register. This resets some internal + status for the MPLK0 through the MPLK3 registers.*/ + gpCGEM_regs->MPLKCMD = (1<MPLK[i] = mem_prot_key[i]; + } + + /*3. Write a 1 to the UNLOCK field in the MPLKCMD register. If the key written in + step 2 matches the stored key, the hardware disengages the lock. If the key written + in step 2 does not match, the hardware signals an exception. The hardware + reports the fault address as the address of the MPLKCMD register.*/ + gpCGEM_regs->MPLKCMD = (1<MPLKSTAT&CSL_CGEM_MPLKSTAT_LK_MASK)); +} + +/***************************************************************************** + Prototype : L1_MPPA_setup + Description : setup the memory protection for local L1 memory + Input : volatile Uint32 MPPA_regs[], Uint32 MPPA[] + Output : None + Return Value : + +usage example: + Uint32 MPPA[16]= + { + MP_LOCAL|MP_SR|MP_UR, //page 0 for read only + MP_LOCAL|MP_SR|MP_SW|MP_UR|MP_UW, //page 1 for read/write + ...... + } + ...... + L1_MPPA_setup(gpCGEM_regs->L1PMPPA, MPPA); + + History : + 1.Date : 2012/12/6 + Author : Brighton Feng + Modification : Created function + +*****************************************************************************/ +void L1_MPPA_setup(volatile Uint32 MPPA_regs[], Uint32 MPPA[]) +{ + int i; + + if(gpCGEM_regs->MPLKSTAT&CSL_CGEM_MPLKSTAT_LK_MASK) + unlock_mem_prot_regs(); + + /*clear any memory protection fault*/ + gpCGEM_regs->L1PMPFCR = 1; + gpCGEM_regs->L1DMPFCR = 1; + + /*setup the memory protection attributes for 32 pages*/ + for(i=0; i<16; i++) + { + MPPA_regs[i] = MPPA[i]; + } + + lock_mem_prot_regs(); +} + +/***************************************************************************** + Prototype : L1P_memory_protection_cfg + Description : config "AccessPermisionMask" for L1P + Input : Uint32 AccessPermisionMask + Output : None + Return Value : +*****************************************************************************/ +void L1P_memory_protection_cfg(Uint32 AccessPermisionMask) +{ + int i; + + if(gpCGEM_regs->MPLKSTAT&CSL_CGEM_MPLKSTAT_LK_MASK) + unlock_mem_prot_regs(); + + /*clear any memory protection fault*/ + gpCGEM_regs->L1PMPFCR = 1; + + /*set L1P only for cacheable local execution, disable all external access*/ + for(i=0; i<16; i++) + { + gpCGEM_regs->L1PMPPA[i] = AccessPermisionMask; + } + + lock_mem_prot_regs(); +} + +/***************************************************************************** + Prototype : L1D_memory_protection_cfg + Description : config "AccessPermisionMask" for L1P + Input : Uint32 AccessPermisionMask + Output : None + Return Value : +*****************************************************************************/ +void L1D_memory_protection_cfg(Uint32 AccessPermisionMask) +{ + int i; + + if(gpCGEM_regs->MPLKSTAT&CSL_CGEM_MPLKSTAT_LK_MASK) + unlock_mem_prot_regs(); + + /*clear any memory protection fault*/ + gpCGEM_regs->L1DMPFCR = 1; + + /*set L1P only for cacheable local execution, disable all external access*/ + for(i=0; i<16; i++) + { + gpCGEM_regs->L1DMPPA[i] = AccessPermisionMask; + } + + lock_mem_prot_regs(); +} + +/***************************************************************************** + Prototype : L1_cache_protection + Description : protect L1 as cache + Input : None + Output : None + Return Value : + + History : + 1.Date : 2012/10/28 + Author : Brighton Feng + Modification : Created function + +*****************************************************************************/ +void L1_cache_protection() +{ + /*set L1P only for cacheable local execution, disable all external access*/ + L1P_memory_protection_cfg(0); + + /*set L1D only for cacheable local read/write, disable all external access*/ + L1D_memory_protection_cfg(0); +} + + +/***************************************************************************** + Prototype : LL2_MPPA_setup + Description : setup the memory protection for local L2 memory + Input : Uint32 MPPA[] + Output : None + Return Value : +usage example: + Uint32 MPPA[32]= + { + MP_LOCAL|MP_SX|MP_UX, //page 0 for local code only + MP_LOCAL|MP_SR|MP_SW|MP_UR|MP_UW, //page 1 for local data only + ...... + } + ...... + LL2_MPPA_setup(MPPA); + + History : + 1.Date : 2012/10/5 + Author : Brighton Feng + Modification : Created function + +*****************************************************************************/ +void LL2_MPPA_setup(Uint32 MPPA[]) +{ + int i; + + if(gpCGEM_regs->MPLKSTAT&CSL_CGEM_MPLKSTAT_LK_MASK) + unlock_mem_prot_regs(); + + /*clear any memory protection fault*/ + gpCGEM_regs->L2MPFCR = 1; + + /*setup the memory protection attributes for 32 pages*/ + for(i=0; i<32; i++) + { + gpCGEM_regs->L2MPPA[i] = MPPA[i]; + } + + lock_mem_prot_regs(); +} + +/***************************************************************************** + Prototype : LL2_Memory_Protection_cfg + Description : config "AccessPermisionMask" for local L2 memory section from + "startAddress" with "byteCount" size + Input : Uint32 startAddress + Uint32 byteCount + Uint32 AccessPermisionMask + Output : None + Return Value : + + History : + 1.Date : 2012/10/5 + Author : Brighton Feng + Modification : Created function + +*****************************************************************************/ +void LL2_Memory_Protection_cfg(Uint32 startAddress, + Uint32 byteCount, Uint32 AccessPermisionMask) +{ + int i; + Uint32 uiEndAddress; + Uint32 uiPageIndex, uiNumPages, uiPageSize, uiPageAddressMask, uiPageShift; + TDSP_Board_Type DSP_Board_Type; + + if(gpCGEM_regs->MPLKSTAT&CSL_CGEM_MPLKSTAT_LK_MASK) + unlock_mem_prot_regs(); + + DSP_Board_Type = KeyStone_Get_dsp_board_type(); + + /*L2 memory protection size is 32KB for TCI6614, C6670, + it is 16KB for C6678*/ + uiPageSize= 32*1024; + uiPageAddressMask= 32*1024-1; + uiPageShift= 15; + if(C6678_EVM == DSP_Board_Type) + { + uiPageSize= 16*1024; + uiPageAddressMask= 16*1024-1; + uiPageShift= 14; + } + + if(startAddress>=0x10800000) + { + printf("LL2 memory protection start Address 0x%x is not a local address\n", + startAddress); + startAddress &= 0xFFFFFF; /*convert to local address*/ + } + uiEndAddress= startAddress+ byteCount; + + if(startAddress&uiPageAddressMask) + { + printf("LL2 memory protection start Address 0x%x does not align to page boundary\n", + startAddress); + startAddress &= (~uiPageAddressMask); + } + uiPageIndex= (startAddress-0x800000)>>uiPageShift; + + byteCount= uiEndAddress- startAddress; + if(byteCount&uiPageAddressMask) + { + printf("LL2 memory protection section size 0x%x is not multiple of page size\n", + byteCount); + byteCount = (byteCount+uiPageSize)&(~uiPageAddressMask); + } + uiNumPages= byteCount>>uiPageShift; + + for(i= 0; iL2MPPA[uiPageIndex+i] = AccessPermisionMask; + + lock_mem_prot_regs(); +} + +/***************************************************************************** + Prototype : KeyStone_CorePac_AID_map + Description : map CorePac AID to PrivID: + map_table[0] assign the PrivID for AID0, + map_table[1] assign the PrivID for AID1 + ...... + map_table[5] assign the PrivID for AID5 + Input : Uint8 map_table[] + Output : None + Return Value : + + History : + 1.Date : 2012/10/5 + Author : Zhan + Modification : Created function + +*****************************************************************************/ +void KeyStone_CorePac_AID_map(Uint8 map_table[]) +{ + int i; + Uint32 *PAMAP= (Uint32 *)&(gpCGEM_regs->PAMAP0); + + /*map all PrivID to AIDx by default*/ + for(i=0; i<16; i++) + PAMAP[i]= CSL_CGEM_PAMAP0_AID_MASK; + + /*map AID0~AID5*/ + for(i=0; i<6; i++) + { + if(map_table[i]<16) /*PrivID must be less than 16*/ + PAMAP[map_table[i]]= i; + } +} + +/***************************************************************************** + Prototype : KeyStone_PrivID_Remap + Description : privilege ID remap to AID + Input : int privID + int AID + Output : None + Return Value : + + History : + 1.Date : 2012/10/5 + Author : Zhan + Modification : Created function + +*****************************************************************************/ +void KeyStone_PrivID_Remap(int privID, int AID) +{ + volatile unsigned int * pamapReg = NULL; + unsigned int val = 0; + + pamapReg = (volatile unsigned int *)(&gpCGEM_regs->PAMAP0 + privID); + + if(AID >= MAX_AID_NUM) + AID = 0; + val = *pamapReg; + + val &= (~CSL_CGEM_PAMAP0_AID_MASK); + + val |= ((AID<>4)) + { + printf("Segment replacement address 0x%x does not start from power-of-2 boundary corresponds to segment size 0x%x.\n", + RADDR, SegementSize); + RADDR &= (~(SegSizeMask>>4)); + printf("Extended replacement address to 0x%x.\n", RADDR); + } + + MPAX_regs->MPAXH= BADDR|(SegSizeBits-1); + MPAX_regs->MPAXL= RADDR|AccessPermisionMask; + +} + +/***************************************************************************** + Prototype : KeyStone_XMC_MPAX_setup + Description : configure multiple MPAX segments in XMC with a configuration + table. + Please note, the code of this function or the data used by this function + (stack, parameters...) can not be put in the segment that will be modified + by this function. Normally, to put this function and its related data in + LL2 is a good idea. + Input : MPAX_Config MPAX_cfg[] + Uint32 firstSeg + Uint32 numSegs + Output : None + Return Value : + + History : + 1.Date : 2012/10/15 + Author : Brighton Feng + Modification : Created function + +*****************************************************************************/ +#pragma CODE_SECTION (KeyStone_XMC_MPAX_setup, ".text:Core_MPAX") +void KeyStone_XMC_MPAX_setup(MPAX_Config MPAX_cfg[], + Uint32 firstSeg, Uint32 numSegs) +{ + int i; + + if(firstSeg >= 16) + { + printf("The XMC MPAX segment number %d >= 16, not supported.\n ", firstSeg); + return; + } + + if(gpCGEM_regs->MPLKSTAT&CSL_CGEM_MPLKSTAT_LK_MASK) + unlock_mem_prot_regs(); + + /*CAUTION: + A MPAX segment can only be modified when there is no access to the space + of this segment. Any data in cache or prefetch buffer from the space of this + segment must be writeback and invalidated before the segment modification. + It is recommended to configure the MPAX at the very beginning of application + software before any shared memory is used. Code and data for CorePac MPAX + configuration should be allocated in LL2. + If a MPAX segment must be modified on-the-fly, the safer way is, to write + the new configuration to a unused higher segment, and then clear the old + segment. This is based on the fact that higher numbered segments take + precedence over lower numbered segments. */ + CACHE_wbInvAllL2(CACHE_WAIT); + CSL_XMC_invalidatePrefetchBuffer(); + _mfence(); + _mfence(); //ensure all writeback invalidate have completed. + + for(i=numSegs-1; i>=0 ; i--) + { + KeyStone_MPAX_seg_setup((MPAX_Regs *)&gpXMC_regs->XMPAX[firstSeg+i], + MPAX_cfg[i].BADDR, MPAX_cfg[i].RADDR, + MPAX_cfg[i].SegementSize, MPAX_cfg[i].AccessPermisionMask); + } + + lock_mem_prot_regs(); +} + +/***************************************************************************** + Prototype : KeyStone_SMS_MPAX_setup + Description : configure multiple MPAX segments in SMS of MSMC with a conf- + iguration table + Input : MPAX_Config MPAX_cfg[] + Uint32 firstSeg + Uint32 numSegs + Uint32 PrivID + Output : None + Return Value : + + History : + 1.Date : 2012/10/15 + Author : Brighton Feng + Modification : Created function + +*****************************************************************************/ +void KeyStone_SMS_MPAX_setup(MPAX_Config MPAX_cfg[], + Uint32 firstSeg, Uint32 numSegs, Uint32 PrivID) +{ + int i; + + if( gpMSMC_regs->SMS_MPAX_LCKSTAT&(1<=0 ; i--) + KeyStone_MPAX_seg_setup( + (MPAX_Regs *)&gpMSMC_regs->SMS_MPAX_PER_PRIVID[PrivID].SMS[firstSeg+i], + MPAX_cfg[i].BADDR, MPAX_cfg[i].RADDR, + MPAX_cfg[i].SegementSize, MPAX_cfg[i].AccessPermisionMask); + + CSL_MSMC_lockSMS(PrivID); +} + +/***************************************************************************** + Prototype : KeyStone_SES_MPAX_setup + Description : configure multiple MPAX segments in SES of MSMC with a conf- + iguration table + Input : MPAX_Config MPAX_cfg[] + Uint32 firstSeg + Uint32 numSegs + Uint32 PrivID + Output : None + Return Value : + + History : + 1.Date : 2012/10/15 + Author : Brighton Feng + Modification : Created function + +*****************************************************************************/ +void KeyStone_SES_MPAX_setup(MPAX_Config MPAX_cfg[], + Uint32 firstSeg, Uint32 numSegs, Uint32 PrivID) +{ + int i; + + if( gpMSMC_regs->SES_MPAX_LCKSTAT&(1<=0 ; i--) + KeyStone_MPAX_seg_setup( + (MPAX_Regs *)&gpMSMC_regs->SES_MPAX_PER_PRIVID[PrivID].SES[firstSeg+i], + MPAX_cfg[i].BADDR, MPAX_cfg[i].RADDR, + MPAX_cfg[i].SegementSize, MPAX_cfg[i].AccessPermisionMask); + + CSL_MSMC_lockSES(PrivID); +} + +/***************************************************************************** + Prototype : KeyStone_MSMC_MP_interrupt_en + Description : Enable MSMC Memory protection error interrupt for PrivIDs + indicated by "PRIVID_MASK" + Input : Uint32 PRIVID_MASK + Output : None + Return Value : + + History : + 1.Date : 2012/10/15 + Author : Zhan + Modification : Created function + +*****************************************************************************/ +void KeyStone_MSMC_MP_interrupt_en(Uint32 PRIVID_MASK) +{ + if(gpMSMC_regs->CFGLCKSTAT&CSL_MSMC_CFGLCKSTAT_WSTAT_MASK) + CSL_MSMC_unlockNonMPAX(); + + /*clear MP fault record*/ + gpMSMC_regs->SMPFCR = 1; + + /*clear interrupt error status flag*/ + gpMSMC_regs->SMIRC = (PRIVID_MASK)<SMIESTAT |= (PRIVID_MASK<> + CSL_CGEM_L2MPFSR_FID_SHIFT; + + printf(" memory protection exception caused by master with ID %d at 0x%x\n", + master_id, MPFAR); + } + + if (MPFSR & CSL_CGEM_L2MPFSR_UX_MASK) { + puts(" User Execute violation"); + } + if (MPFSR & CSL_CGEM_L2MPFSR_UW_MASK) { + puts(" User Write violation"); + } + if (MPFSR & CSL_CGEM_L2MPFSR_UR_MASK) { + puts(" User Read violation"); + } + if (MPFSR & CSL_CGEM_L2MPFSR_SX_MASK) { + puts(" Supervisor Execute violation"); + } + if (MPFSR & CSL_CGEM_L2MPFSR_SW_MASK) { + puts(" Supervisor Write violation"); + } + if (MPFSR & CSL_CGEM_L2MPFSR_SR_MASK) { + puts(" Supervisor Read violation"); + } + +} + +/***************************************************************************** + Prototype : KeyStone_MSMC_protection_exception_handler + Description : MSMC memory protection processing + Input : None + Output : None + Return Value : +*****************************************************************************/ +void KeyStone_MSMC_protection_exception_handler() +{ + unsigned int master_id; + unsigned int priv_id; + unsigned int address; + unsigned int NM; + + address = gpMSMC_regs->SMPFAR; + + master_id = (gpMSMC_regs->SMPFR&CSL_MSMC_SMPFR_FMSTID_MASK)>> + CSL_MSMC_SMPFR_FMSTID_SHIFT; + priv_id = (gpMSMC_regs->SMPFR&CSL_MSMC_SMPFR_FPID_MASK)>> + CSL_MSMC_SMPFR_FPID_SHIFT; + + exception_record.status.ext_sts.info.memory.fault_address= address; + exception_record.status.ext_sts.info.memory.fault_status.SMPFR= gpMSMC_regs->SMPFR; + + NM = (gpMSMC_regs->SMPFXR & CSL_MSMC_SMPFXR_NM_MASK) >> CSL_MSMC_SMPFXR_NM_SHIFT; + + printf(" memory protection exception caused by master %d (PrivID= %d) at address 0x%x\n", + master_id, priv_id, address); + + if(1 == NM) + { + printf(" Fault is caused by the address not matching any of the segment BADDR\n"); + } + + if(gpMSMC_regs->CFGLCKSTAT&CSL_MSMC_CFGLCKSTAT_WSTAT_MASK) + CSL_MSMC_unlockNonMPAX(); + /*clear fault record*/ + gpMSMC_regs->SMPFCR = 1; + /*clear interrupt error status flag*/ + gpMSMC_regs->SMIRC = (1<PROG_START_ADDRESS = uiStartAddress; + MPPA_regs->PROG_END_ADDRESS = uiEndAddress; + MPPA_regs->PROG_MPPA = AccessPermisionMask; +} + +/***************************************************************************** + Prototype : KeyStone_MPU_setup + Description : peripherals MPU ranges configuration + Input : Uint32 uiMPU_num: number of the MPU to be setup + MPU_Range_Config MPU_cfg[]: MPU ranges configuration table + Uint32 numRangeCfg: number of ranges to be configured + Output : None + Return Value : + + History : + 1.Date : 2012/12/15 + Author : Brighton Feng + Modification : Created function +*****************************************************************************/ +void KeyStone_MPU_setup(Uint32 uiMPU_num, + MPU_Range_Config MPU_cfg[], Uint32 numRangeCfg) +{ + int i; + unsigned int mpuNumProgmableRange; + CSL_MpuRegs * mpuRegs; + + /*For Turbo Nyquist, add following code to modify initial value, + Or user can modify the initail values directly*/ + if(5==uiMPU_num) + TN_MPU5_constant(); + + mpuRegs= gpMPU_regs[uiMPU_num]; + + mpuNumProgmableRange = (mpuRegs->CONFIG & CSL_MPU_CONFIG_NUM_PROG_MASK)>>CSL_MPU_CONFIG_NUM_PROG_SHIFT; + if(mpuNumProgmableRange == 0) + { + mpuNumProgmableRange = 16; + } + + if(numRangeCfg>mpuNumProgmableRange) + { + printf("MPU %d programmable ranges %d < %d.\n", + uiMPU_num, mpuNumProgmableRange, numRangeCfg); + numRangeCfg=mpuNumProgmableRange; + } + else if(numRangeCfg gstruMpuAddrRange[uiMPU_num].EndAddr) ) + { + printf("The configuration address is out of MPU %d protection range\n", + uiMPU_num); + continue; + } + + KeyStone_MPU_range_setup(&mpuRegs->PROG_REGION[i], + MPU_cfg[i].StartAddr, MPU_cfg[i].EndAddr, + MPU_cfg[i].AccessPermisionMask); + + } + + //clear unused ranges + for( ;iPROG_REGION[i].PROG_MPPA = 0; + } + + //clear status + mpuRegs->FAULT_CLEAR = 1; + mpuRegs->INT_ENABLED_STATUS_CLEAR = + CSL_MPU_INT_ENABLED_STATUS_CLEAR_ENABLED_ADDR_ERR_MASK + |CSL_MPU_INT_ENABLED_STATUS_CLEAR_ENABLED_PROT_ERR_MASK; + + /* enable the interrupt */ + mpuRegs->INT_ENABLE = CSL_MPU_INT_ENABLE_ADDR_ERR_EN_MASK + | CSL_MPU_INT_ENABLE_PROT_ERR_EN_MASK; + + return; +} + +/***************************************************************************** + Prototype : KeyStone_MPU_MPPA_modify + Description : search the range which match a address and then modify + the access permission of that range. + Input : Uint32 uiMPU_num: number of the MPU to be modifed + Uint32 uiAddress: address which need modify permision + Uint32 AccessPermisionMask: permission mask for that range + Output : None + Return Value : + + History : + 1.Date : 2012/12/13 + Author : Brighton Feng + Modification : Created function +*****************************************************************************/ +void KeyStone_MPU_MPPA_modify(Uint32 uiMPU_num, + Uint32 uiAddress, Uint32 AccessPermisionMask) +{ + int i; + unsigned int mpuNumProgmableRange; + CSL_MpuRegs * mpuRegs; + + /*For Turbo Nyquist, add following code to modify initial value, + Or user can modify the initail values directly*/ + if(5==uiMPU_num) + TN_MPU5_constant(); + + mpuRegs= gpMPU_regs[uiMPU_num]; + + mpuNumProgmableRange = (mpuRegs->CONFIG & CSL_MPU_CONFIG_NUM_PROG_MASK)>>CSL_MPU_CONFIG_NUM_PROG_SHIFT; + if(mpuNumProgmableRange == 0) + { + mpuNumProgmableRange = 16; + } + + /*search through all ranges*/ + for(i=0; i< mpuNumProgmableRange; i++) + { + /*match with one range*/ + if((uiAddress >= mpuRegs->PROG_REGION[i].PROG_START_ADDRESS) + &&(uiAddress <= mpuRegs->PROG_REGION[i].PROG_END_ADDRESS)) + { + mpuRegs->PROG_REGION[i].PROG_MPPA = AccessPermisionMask; + return; + } + } + + printf("address 0x%08x does not match any range in MPU %d\n", + uiAddress, uiMPU_num); + + return; +} + +/***************************************************************************** + Prototype : KeyStone_MPU_interrupts_enable + Description : enable the all MPU interrupts + Input : None + Output : None + Return Value : + + History : + 1.Date : 2012/10/28 + Author : Brighton Feng + Modification : Created function + +*****************************************************************************/ +void KeyStone_MPU_interrupt_enable(Uint32 uiMPU_num) +{ + if((gpMPU_regs[uiMPU_num]->REVISION&0xFFFF0000)!= + (CSL_MPU_REVISION_RESETVAL&0xFFFF0000)) + { + printf("Can't read MPU%d ID register, make sure corresponding power domain is enabled.", uiMPU_num); + return; + } + + gpMPU_regs[uiMPU_num]->FAULT_CLEAR = 1; + gpMPU_regs[uiMPU_num]->INT_ENABLED_STATUS_CLEAR = + CSL_MPU_INT_ENABLED_STATUS_CLEAR_ENABLED_ADDR_ERR_MASK + |CSL_MPU_INT_ENABLED_STATUS_CLEAR_ENABLED_PROT_ERR_MASK; + gpMPU_regs[uiMPU_num]->INT_ENABLE = CSL_MPU_INT_ENABLE_ADDR_ERR_EN_MASK + |CSL_MPU_INT_ENABLE_PROT_ERR_EN_MASK; + +} +void KeyStone_MPU_interrupts_enable() +{ + int i; + TDSP_Board_Type DSP_Board_Type = KeyStone_Get_dsp_board_type(); + + TN_MPU5_constant(); + + for(i=0; i<4; i++) + { + KeyStone_MPU_interrupt_enable(i); + } + + if((C6670_EVM== DSP_Board_Type) + ||(TCI6614_EVM== DSP_Board_Type)) + { + for(i=4; i<6; i++) + { + /*MPU5 (for BCP) of TCI6614 is only accessible + when BCP is enabled through PSC*/ + if((5==i)&&(TCI6614_EVM== DSP_Board_Type)&& + ((CSL_PSC_getPowerDomainState(5) != PSC_PDSTATE_ON) || + (CSL_PSC_getModuleState (12) != PSC_MODSTATE_ENABLE))) + { + puts("Enable power domain for MPU5 before configure it."); + continue; + } + + KeyStone_MPU_interrupt_enable(i); + } + } + + if(TCI6614_EVM== DSP_Board_Type) + { + for(i=6; i<8; i++) + { + KeyStone_MPU_interrupt_enable(i); + } + } + + return; +} + +char * Peri_MPU_err_type_str[]= +{ + "User execution fault!", + "User write fault!", + "User read fault!", + "Supervisor execution fault!", + "Supervisor write fault!", + "Supervisor read fault!" +}; + +char * Ns_str[]= +{ + "secure", + "non-secure" +}; +/***************************************************************************** + Prototype : KeyStone_peripherals_MPU_fault_status + Description : Print the MPU error information + Input : unsigned int uwFltStatus + unsigned int uwFltAddr + Output : None + Return Value : +*****************************************************************************/ +void KeyStone_peripherals_MPU_fault_status(unsigned int uwFltStatus, + unsigned int uwFltAddr) +{ + unsigned int MSTID; + unsigned int PRIVID; + unsigned int NS; + unsigned int FaultType; + unsigned int BitsCnt; + + MSTID = (uwFltStatus & CSL_MPU_FAULT_STATUS_MSTID_MASK)>>CSL_MPU_FAULT_STATUS_MSTID_SHIFT; + PRIVID = (uwFltStatus & CSL_MPU_FAULT_STATUS_PRIVID_MASK)>>CSL_MPU_FAULT_STATUS_PRIVID_SHIFT; + NS = (uwFltStatus & CSL_MPU_FAULT_STATUS_NS_MASK)>>CSL_MPU_FAULT_STATUS_NS_SHIFT; + printf(" The MSTID %d (PRIVID %d) triggered MPU error at 0x%x with %s access\n", + MSTID, PRIVID, uwFltAddr, Ns_str[NS]); + + FaultType = (uwFltStatus & CSL_MPU_FAULT_STATUS_FAULT_TYPE_MASK) >> CSL_MPU_FAULT_STATUS_FAULT_TYPE_SHIFT; + if(1==(_dotpu4(_bitc4(FaultType), 0x01010101))) + { + BitsCnt= 31 - _lmbd(1, FaultType); + printf(" %s\n",Peri_MPU_err_type_str[BitsCnt]); + } + else if(0x3F == FaultType) + { + puts(" Relaxed cache line fill fault!"); + } + else if(0x12 == FaultType) + { + puts(" Relaxed cache write back fault!"); + } +} +/***************************************************************************** + Prototype : KeyStone_peripherals_MPU_excepiton_handler + Description : peripheral MPU processing + Input : Uint32 uwMpuNum + Output : None + Return Value : +*****************************************************************************/ +void KeyStone_peripherals_MPU_excepiton_handler(Uint32 uwMpuNum) +{ + Uint32 uwStatus; + Uint32 uwFltAddr; + Uint32 uwFltStatus; + CSL_MpuRegs *pstruMpuRegs= gpMPU_regs[uwMpuNum]; + + uwStatus = pstruMpuRegs->INT_ENABLED_STATUS_CLEAR; + if(uwStatus & 0x2) + { + printf(" MPU %d address violation error\n", uwMpuNum); + pstruMpuRegs->INT_ENABLED_STATUS_CLEAR = 2; + } + + if(uwStatus & 0x1) + { + printf(" MPU %d protection violation error\n", uwMpuNum); + pstruMpuRegs->INT_ENABLED_STATUS_CLEAR = 1; + } + + uwFltAddr = pstruMpuRegs->FAULT_ADDRESS; + uwFltStatus = pstruMpuRegs->FAULT_STATUS; + exception_record.status.ext_sts.info.memory.fault_address= uwFltAddr; + exception_record.status.ext_sts.info.memory.fault_status.MPU_FAULT_STATUS= uwFltStatus; + + KeyStone_peripherals_MPU_fault_status(uwFltStatus,uwFltAddr); + pstruMpuRegs->FAULT_CLEAR = 1; + + pstruMpuRegs->EOI = 0; +} + + +/*======================memory EDC=====================================*/ +/***************************************************************************** + Prototype : KeyStone_SL2_EDC_enable + Description : Enable MSMC EDC + Input : scrubCnt, number of MSMC clock cycles between scrubbing + Output : None + Return Value : + + History : + 1.Date : 2012/10/15 + Author : Brighton Feng + Modification : Created function + +*****************************************************************************/ +void KeyStone_SL2_EDC_enable(Uint32 scrubCnt) +{ + if(gpMSMC_regs->CFGLCKSTAT&CSL_MSMC_CFGLCKSTAT_WSTAT_MASK) + CSL_MSMC_unlockNonMPAX(); + + /*Software must wait for the PRR (Parity RAM Ready) bit before making + the first read access to MSMC RAM after reset.*/ + while(0==(gpMSMC_regs->SMEDCC&CSL_MSMC_SMEDCC_PRR_MASK)); + + /* set scrubbing period value */ + if(scrubCnt>255) + scrubCnt= 255; + CSL_MSMC_setCounterBankRefreshRead(scrubCnt); //the scrubbing engine works every scrubCnt*1024 cycle*/ + + /* clear EDC errors and enable EDC event*/ + gpMSMC_regs->SMIRC = 0xf; + gpMSMC_regs->SMIESTAT |= (CSL_MSMC_SMIESTAT_NCSIE_MASK + | CSL_MSMC_SMIESTAT_CSIE_MASK + | CSL_MSMC_SMIESTAT_NCEIE_MASK + | CSL_MSMC_SMIESTAT_CEIE_MASK); + + //enable SL2 EDC + CSL_MSMC_setECM(1); + + CSL_MSMC_lockNonMPAX(); +} + +/***************************************************************************** + Prototype : KeyStone_SL2_EDC_interrupt_en + Description : Enable MSMC EDC error interrupt + Input : None + Output : None + Return Value : + + History : + 1.Date : 2012/10/15 + Author : Brighton Feng + Modification : Created function + +*****************************************************************************/ +void KeyStone_SL2_EDC_interrupt_en() +{ + if(gpMSMC_regs->CFGLCKSTAT&CSL_MSMC_CFGLCKSTAT_WSTAT_MASK) + CSL_MSMC_unlockNonMPAX(); + + /* clear EDC errors*/ + gpMSMC_regs->SMIRC = 0xf; + + /* Enable EDC error interrupt */ + gpMSMC_regs->SMIESTAT |= (CSL_MSMC_SMIESTAT_NCSIE_MASK + | CSL_MSMC_SMIESTAT_CSIE_MASK + | CSL_MSMC_SMIESTAT_NCEIE_MASK + | CSL_MSMC_SMIESTAT_CEIE_MASK); + + CSL_MSMC_lockNonMPAX(); +} + +/***************************************************************************** + Prototype : LL2_EDC_setup + Description : Eenable LL2 EDC and scrub whole LL2 + Input : None + Output : None + Return Value : + + History : + 1.Date : 2012/10/10 + Author : Jane + Modification : Created function + + 2.Date : 2012/10/20 + Author : Brighton Feng + +*****************************************************************************/ +void LL2_EDC_setup() +{ + int i; + unsigned int uiByteCnt= 512*1024; + TDSP_Board_Type DSP_Board_Type; + + /* 1. Disable the EDC */ + CSL_CGEM_disableL2EDC(); + + /* 2. Clear any EDC errors */ + CSL_CGEM_clearL2EDCErrorStatus(1, 1, 1, 1); + + /* 3. Memory Scrubbing with IDMA, generate the parity bits*/ + DSP_Board_Type = KeyStone_Get_dsp_board_type(); + if((DUAL_NYQUIST_EVM == DSP_Board_Type) + ||(C6670_EVM == DSP_Board_Type) + ||(TCI6614_EVM == DSP_Board_Type)) + { + uiByteCnt= 1024*1024; + } + + /*Each IDMA can transfer up to 65532 bytes, + here we transfer 32KB each time*/ + for(i=0; i< (uiByteCnt>>15); i++) + { + IDMA_copy((0x00800000 + i*(1<<15)), (0x00800000 + i*(1<<15)), + (1<<15), DMA_WAIT); + } + + /* 4. Enable the EDC*/ + CSL_CGEM_enableL2EDC(); + gpCGEM_regs->L2EDCEN= (1<= uiLL2EndAddress) + uiLL2_scrub_addr=0x800000; + +} + +/***************************************************************************** + Prototype : L1P_EDC_setup + Description : enable L1P ED and scrub whole L1P + Input : None + Output : None + Return Value : + + History : + 1.Date : 2012/10/10 + Author : Jane + Modification : Created function + + 2.Date : 2012/10/30 + Author : Brighton Feng +*****************************************************************************/ +void L1P_EDC_setup() +{ + Uint32 preL1PMPPA[16]; + + /* 1. Disable the EDC */ + CSL_CGEM_disablePMCErrorDetection(); + + /* 2. Clear any EDC errors */ + CSL_CGEM_clearPMCErrorDetectionStatus(1, 1); + + /* 3. Memory Scrubbing with IDMA, generate the parity bits*/ + memcpy(preL1PMPPA, (void *)gpCGEM_regs->L1PMPPA, 64);//save protection attributes + L1P_memory_protection_cfg(0xFFFF); //enable IDMA access to L1P + IDMA_copy(0x00E00000, 0x00E00000, 32*1024, DMA_WAIT); + L1_MPPA_setup(gpCGEM_regs->L1PMPPA, preL1PMPPA);//restore protection for L1 + + /* 4. Enable the EDC*/ + CSL_CGEM_enablePMCErrorDetection(); +} + +char * LL2_EDC_victim_err_str="LL2 victims"; +char * LL2_EDC_DMA_err_str= "DMA access"; +char * LL2_EDC_L1D_err_str= "L1D access"; +char * LL2_EDC_L1P_err_str= "L1P access"; + +/***************************************************************************** + Prototype : LL2_EDC_handler + Description : LL2 EDC exception/interrupt handler + Input : None + Output : None + Return Value : + + History : + 1.Date : 2012/10/28 + Author : Brighton Feng + Modification : Created function + +*****************************************************************************/ +void LL2_EDC_handler(Bool bCorrected) +{ + /* EDC error during the L1D access */ + Uint8 derr; + /* EDC error during the L1P access */ + Uint8 perr; + /* EDC error during the DMA access*/ + Uint8 dmaerr; + /* EDC error during the L2 victim occurred */ + Uint8 verr; + /* single bit or dual bit EDC error */ + Uint8 nerr; + + char *errStr; + Uint32 errAddr; + + /* Get the all LL2 error status */ + CSL_CGEM_getL2EDCErrorStatus(&derr, &perr, &dmaerr, &verr, &nerr); + + if(derr|perr|dmaerr|verr) + { + errAddr= gpCGEM_regs->L2EDADDR&CSL_CGEM_L2EDADDR_ADDR_MASK; + + exception_record.status.ext_sts.info.memory.fault_address= errAddr; + exception_record.status.ext_sts.info.memory.fault_status.L2EDSTAT= + gpCGEM_regs->L2EDSTAT; + + if(bCorrected) + { + printf(" LL2 EDC (correctable) at bit %d of ",(gpCGEM_regs->L2EDSTAT& + CSL_CGEM_L2EDSTAT_BITPOS_MASK)>>CSL_CGEM_L2EDSTAT_BITPOS_SHIFT); + + //scrub 64 bytes including the error address to correct the error + if(perr) //by L1P access + IDMA_copy(errAddr&0xFFFFFFC0, errAddr&0xFFFFFFC0, 64, DMA_WAIT); + else + { + volatile Uint32 * uipAddress= (volatile Uint32 *)(errAddr&0xFFFFFFC0); + /*read one word into a cache line, and write to make it dirty, + which will be automatically written back sooner or later*/ + *uipAddress= *uipAddress; + } + } + else + { + printf(" LL2 EDC error (non-correctable) at "); + } + errStr = (char *)(perr * (Uint32)LL2_EDC_L1P_err_str + + derr * (Uint32)LL2_EDC_L1D_err_str + + verr * (Uint32)LL2_EDC_victim_err_str + + dmaerr * (Uint32)LL2_EDC_DMA_err_str); + + printf("address 0x%x caused by %s.\n", + errAddr, + errStr); + + if(0==(gpCGEM_regs->L2EDADDR&CSL_CGEM_L2EDADDR_RAM_MASK)) + { + printf(" Error detected in Way %d of L2 cache\n", + (gpCGEM_regs->L2EDADDR&CSL_CGEM_L2EDADDR_WAY_MASK)>>CSL_CGEM_L2EDADDR_WAY_SHIFT); + } + + printf(" total non-correctable error number= %d, total correctable error number= %d.\n", + gpCGEM_regs->L2EDCNEC, gpCGEM_regs->L2EDCPEC); + + CSL_CGEM_clearL2EDCErrorStatus(derr, perr, dmaerr, verr); + } + else + { + puts(" Enter LL2 EDC handler, but no error flag is set!"); + } +} +/***************************************************************************** + Prototype : L1P_ED_handler + Description : L1P EDC processing + Input : None + Output : None + Return Value : + + History : + 1.Date : 2012/10/28 + Author : Brighton Feng + Modification : Created function + +*****************************************************************************/ +void L1P_ED_handler() +{ + Uint32 errAddr; + Uint8 errRAM; + + /* EDC error during DMA access */ + Uint8 dmaerr; + /* EDC error during program fetch access */ + Uint8 perr; + + /* Read PMC EDC status*/ + CSL_CGEM_getPMCErrorDetectionStatus(&dmaerr, &perr); + + if(perr|dmaerr) + { + CSL_CGEM_getPMCErrorInfo(&errAddr, &errRAM); + + exception_record.status.ext_sts.info.memory.fault_address= errAddr*32; + exception_record.status.ext_sts.info.memory.fault_status.L1PEDSTAT= + gpCGEM_regs->L1PEDSTAT; + + if(errRAM) + printf(" L1P RAM "); + else + printf(" L1P Cache "); + + printf("parity check error caused by "); + + if(perr == 1) + { + printf("program fetch "); + + /*flush wrong code in L1P. Code will be refetched from L2*/ + CACHE_invL1p((void *)NRP, 64, CACHE_WAIT); + } + else if(dmaerr == 1) + { + printf("DMA "); + } + printf("at address 0x%x\n", errAddr*32); + + CSL_CGEM_clearPMCErrorDetectionStatus(dmaerr,perr); + } +} + + +/***************************************************************************** + Prototype : KeyStone_SL2_EDC_handler + Description : SL2 EDC Processing + Input : None + Output : None + Return Value : + + History : + 1.Date : 2012/10/28 + Author : Brighton Feng + Modification : Created function + +*****************************************************************************/ +void KeyStone_SL2_EDC_handler() +{ + /* EDC correctable error during scrubbing cycle */ + Uint8 cses; + /* EDC non-correctable error during scrubbing cycle */ + Uint8 ncses; + /* EDC correctable error during SRAM access*/ + Uint8 cees; + /* EDC non-correctable error during SRAM access*/ + Uint8 ncees; + /* protection fault status*/ + Uint16 pfeStat; + + /* error address */ + Uint32 errAddr, bitPos, PrivID; + + if(gpMSMC_regs->CFGLCKSTAT&CSL_MSMC_CFGLCKSTAT_WSTAT_MASK) + CSL_MSMC_unlockNonMPAX(); + + CSL_MSMC_getPendingInterrupts(&pfeStat, &cees, &ncees, &cses, &ncses); + + exception_record.status.ext_sts.info.memory.fault_status.SMESTAT= + gpMSMC_regs->SMESTAT; + + if((cses == 1)||(ncses == 1)) + { + if(cses == 1) + { + /*scrubbing engine report address offset from 0*/ + errAddr = (gpMSMC_regs->SMCEA&0xFFFFFF)+0xc000000; + exception_record.status.ext_sts.info.memory.fault_address= errAddr; + + bitPos = (gpMSMC_regs->SMCEA&CSL_MSMC_SMCEA_ESYN_MASK) + >>CSL_MSMC_SMCEA_ESYN_SHIFT; + printf("SL2 Correctable error occurred at bit %d of address 0x%x by scrubbing\n", + bitPos, errAddr); + } + if(ncses == 1) + { + /*scrubbing engine report address offset from 0*/ + errAddr = gpMSMC_regs->SMNCEA+0xc000000; + exception_record.status.ext_sts.info.memory.fault_address= errAddr; + + printf("SL2 Non-correctable error occurred at address 0x%x by scrubbing\n", errAddr); + } + printf("%d correctable errors, %d non-correctable errors occurred during scrubbing.\n", + (gpMSMC_regs->SMSECC&CSL_MSMC_SMSECC_SCEC_MASK) + >>CSL_MSMC_SMSECC_SCEC_SHIFT, + (gpMSMC_regs->SMSECC&CSL_MSMC_SMSECC_SNCEC_MASK) + >>CSL_MSMC_SMSECC_SNCEC_SHIFT); + } + if(cees == 1) + { + volatile Uint32 scrubValue; + + errAddr = gpMSMC_regs->SMCERRAR; + exception_record.status.ext_sts.info.memory.fault_address= errAddr; + + //scrub the address to correct the error + scrubValue= *(volatile Uint32 *)errAddr; //touch to cach + *(volatile Uint32 *)errAddr= scrubValue; //make cache dirty + CACHE_wbInvL2((void *)errAddr, 32, CACHE_WAIT); + + bitPos = (gpMSMC_regs->SMCERRXR&CSL_MSMC_SMCERRXR_ESYN_MASK) + >>CSL_MSMC_SMCERRXR_ESYN_SHIFT; + PrivID = (gpMSMC_regs->SMCERRXR&CSL_MSMC_SMCERRXR_SEPID_MASK) + >>CSL_MSMC_SMCERRXR_SEPID_SHIFT; + printf("SL2 Correctable error occurred at bit %d of address 0x%x by PrivID %d ", + bitPos, errAddr, PrivID); + if(gpMSMC_regs->SMCERRXR&CSL_MSMC_SMCERRXR_SER_MASK) + printf("(not from C66x CorePacs)\n"); + else + printf("(from C66x CorePacs)\n"); + } + if(ncees ==1) + { + errAddr = gpMSMC_regs->SMNCERRAR; + exception_record.status.ext_sts.info.memory.fault_address= errAddr; + + PrivID = (gpMSMC_regs->SMNCERRXR&CSL_MSMC_SMNCERRXR_SEPID_MASK) + >>CSL_MSMC_SMNCERRXR_SEPID_SHIFT; + printf("SL2 Non-correctable error occurred at address 0x%x by PrivID %d ", + errAddr, PrivID); + if(gpMSMC_regs->SMNCERRXR&CSL_MSMC_SMNCERRXR_SER_MASK) + printf("(not from C66x CorePacs)\n"); + else + printf("(from C66x CorePacs)\n"); + } + + /* clear EDC error status */ + CSL_MSMC_clearRawInterruptStatus(0, cees,ncees, cses, ncses); + + CSL_MSMC_lockNonMPAX(); +} + +/*===============================Exception=============================*/ +//data structure to save exception info +Exception_Record exception_record; + +/*some exception events routed from CIC to INTC and then to exception moduel, +all these events are routed to one input of INTC*/ +Uint32 guwIntcCICExcEvtIdx= 95; /*INTC event number mapping to CIC exception events*/ +Uint32 gCIC_EXC_out_num = 15; //CIC output event number +Uint32 gCIC_EXC_EN_MASK[8]= {0,0,0,0,0,0,0,0}; +/***************************************************************************** + Prototype : KeyStone_CIC_exception_events_mapping + Description : CIC exception event mapping to the NMI external exception + Input : void + Output : None + Return Value : + + History : + 1.Date : 2012/10/5 + Author : Brighton Feng + Modification : Created function + + 2.Date : 2012/10/20 + Author : Zhan + Modification : Add event for TCI6614 + + 3.Date : 2012/10/28 + Author : Brighton Feng +*****************************************************************************/ +void KeyStone_CIC_exception_events_mapping(void) +{ + TDSP_Board_Type DSP_Board_Type= KeyStone_Get_dsp_board_type(); + +#if 1 + if(C6670_EVM==DSP_Board_Type + ||DUAL_NYQUIST_EVM==DSP_Board_Type + ||TCI6614_EVM==DSP_Board_Type) + { + gCIC_EXC_out_num= 15+16*DNUM; + } + else if(C6678_EVM==DSP_Board_Type) + { + if(DNUM<4) + gCIC_EXC_out_num= 7+8*DNUM; + else + { + gCIC_EXC_out_num= 7+8*(DNUM-4); + gpCIC_regs= gpCIC1_regs; + } + } + else + { + puts("Unknown DSP board type!"); + return; + } +#endif + + /*-----------------------CP_INTC configuration---------------------*/ + /* Disable Global host interrupts. */ + gpCIC_regs->GLOBAL_ENABLE_HINT_REG= 0; + + /* route following system events to CIC out (event 22 of INTC), and then to exception + TCI6614, C6670, C6678: + CIC: 0 EDMA3CC1 EDMACC_ERRINT EDMA3CC1 error interrupt + CIC: 2 EDMA3CC1 EDMATC_ERRINT0 EDMA3CC1 EDMA3TC0 error interrupt + CIC: 3 EDMA3CC1 EDMATC_ERRINT1 EDMA3CC1 EDMA3TC1 error interrupt + CIC: 4 EDMA3CC1 EDMATC_ERRINT2 EDMA3CC1 EDMA3TC2 error interrupt + CIC: 5 EDMA3CC1 EDMATC_ERRINT3 EDMA3CC1 EDMA3TC3 error interrupt + CIC: 16 EDMA3CC2 EDMACC_ERRINT EDMA3CC2 error interrupt + CIC: 18 EDMA3CC2 EDMATC_ERRINT0 EDMA3CC2 EDMA3TC0 error interrupt + CIC: 19 EDMA3CC2 EDMATC_ERRINT1 EDMA3CC2 EDMA3TC1 error interrupt + CIC: 20 EDMA3CC2 EDMATC_ERRINT2 EDMA3CC2 EDMA3TC2 error interrupt + CIC: 21 EDMA3CC2 EDMATC_ERRINT3 EDMA3CC2 EDMA3TC3 error interrupt + CIC: 32 EDMA3CC0 EDMACC_ERRINT EDMA3CC0 error interrupt + CIC: 34 EDMA3CC0 EDMATC_ERRINT0 EDMA3CC0 EDMA3TC0 error interrupt + CIC: 35 EDMA3CC0 EDMATC_ERRINT1 EDMA3CC0 EDMA3TC1 error interrupt + CIC: 99 MSMC_dedc_nc_error Non-correctable soft error detected on SRAM read + CIC: 100 MSMC_scrub_nc_error Non-correctable soft error detected during scrub cycle + CIC: 102 MSMC_mpf_error8 Memory protection fault indicators for each system master PrivID + CIC: 103 MSMC_mpf_error9 Memory protection fault indicators for each system master PrivID + CIC: 104 MSMC_mpf_error10 Memory protection fault indicators for each system master PrivID + CIC: 105 MSMC_mpf_error11 Memory protection fault indicators for each system master PrivID + CIC: 106 MSMC_mpf_error12 Memory protection fault indicators for each system master PrivID + CIC: 107 MSMC_mpf_error13 Memory protection fault indicators for each system master PrivID + CIC: 108 MSMC_mpf_error14 Memory protection fault indicators for each system master PrivID + CIC: 109 MSMC_mpf_error15 Memory protection fault indicators for each system master PrivID + CIC: 110 DDR3_ERR DDR3 ECC Error Interrupt + TCI6614, C6670: + CIC: 170 MSMC_mpf_error4 Memory protection fault indicators for each system master PrivID + CIC: 171 MSMC_mpf_error5 Memory protection fault indicators for each system master PrivID + CIC: 172 MSMC_mpf_error6 Memory protection fault indicators for each system master PrivID + CIC: 173 MSMC_mpf_error7 Memory protection fault indicators for each system master PrivID + */ + KeyStone_CIC_event_map(gpCIC_regs, 0 , gCIC_EXC_out_num); + KeyStone_CIC_event_map(gpCIC_regs, 2 , gCIC_EXC_out_num); + KeyStone_CIC_event_map(gpCIC_regs, 3 , gCIC_EXC_out_num); + KeyStone_CIC_event_map(gpCIC_regs, 4 , gCIC_EXC_out_num); + KeyStone_CIC_event_map(gpCIC_regs, 5 , gCIC_EXC_out_num); + KeyStone_CIC_event_map(gpCIC_regs, 16, gCIC_EXC_out_num); + KeyStone_CIC_event_map(gpCIC_regs, 18, gCIC_EXC_out_num); + KeyStone_CIC_event_map(gpCIC_regs, 19, gCIC_EXC_out_num); + KeyStone_CIC_event_map(gpCIC_regs, 20, gCIC_EXC_out_num); + KeyStone_CIC_event_map(gpCIC_regs, 21, gCIC_EXC_out_num); + gCIC_EXC_EN_MASK[0] |= + (1<<0 ) + |(1<<2 ) + |(1<<3 ) + |(1<<4 ) + |(1<<5 ) + |(1<<16) + |(1<<18) + |(1<<19) + |(1<<20) + |(1<<21); + + KeyStone_CIC_event_map(gpCIC_regs, 32, gCIC_EXC_out_num); + KeyStone_CIC_event_map(gpCIC_regs, 34, gCIC_EXC_out_num); + KeyStone_CIC_event_map(gpCIC_regs, 35, gCIC_EXC_out_num); + gCIC_EXC_EN_MASK[1] |= + (1<<(32-32)) + |(1<<(34-32)) + |(1<<(35-32)); + + KeyStone_CIC_event_map(gpCIC_regs, 99, gCIC_EXC_out_num); + KeyStone_CIC_event_map(gpCIC_regs, 100, gCIC_EXC_out_num); + KeyStone_CIC_event_map(gpCIC_regs, 102, gCIC_EXC_out_num); + KeyStone_CIC_event_map(gpCIC_regs, 103, gCIC_EXC_out_num); + KeyStone_CIC_event_map(gpCIC_regs, 104, gCIC_EXC_out_num); + KeyStone_CIC_event_map(gpCIC_regs, 105, gCIC_EXC_out_num); + KeyStone_CIC_event_map(gpCIC_regs, 106, gCIC_EXC_out_num); + KeyStone_CIC_event_map(gpCIC_regs, 107, gCIC_EXC_out_num); + KeyStone_CIC_event_map(gpCIC_regs, 108, gCIC_EXC_out_num); + KeyStone_CIC_event_map(gpCIC_regs, 109, gCIC_EXC_out_num); + KeyStone_CIC_event_map(gpCIC_regs, 110, gCIC_EXC_out_num); + gCIC_EXC_EN_MASK[3] |= + (1<<(99 -32*3)) + |(1<<(100-32*3)) + |(1<<(102-32*3)) + |(1<<(103-32*3)) + |(1<<(104-32*3)) + |(1<<(105-32*3)) + |(1<<(106-32*3)) + |(1<<(107-32*3)) + |(1<<(108-32*3)) + |(1<<(109-32*3)) + |(1<<(110-32*3)); + + if(C6670_EVM==DSP_Board_Type + ||DUAL_NYQUIST_EVM==DSP_Board_Type + ||TCI6614_EVM==DSP_Board_Type) + { + KeyStone_CIC_event_map(gpCIC_regs, 170, gCIC_EXC_out_num); + KeyStone_CIC_event_map(gpCIC_regs, 171, gCIC_EXC_out_num); + KeyStone_CIC_event_map(gpCIC_regs, 172, gCIC_EXC_out_num); + KeyStone_CIC_event_map(gpCIC_regs, 173, gCIC_EXC_out_num); + gCIC_EXC_EN_MASK[5] |= + (1<<(170-32*5)) + |(1<<(171-32*5)) + |(1<<(172-32*5)) + |(1<<(173-32*5)); + } + + /* ----------- Mapping MPU interrupt for different chips start -----------------------*/ + if(C6670_EVM==DSP_Board_Type + ||DUAL_NYQUIST_EVM==DSP_Board_Type + ||C6678_EVM==DSP_Board_Type) + { + /* route the following system events to CIC out + CIC: 90 MPU0 addressing violation interrupt and protection violation interrupt + CIC: 92 MPU1 addressing violation interrupt and protection violation interrupt + CIC: 94 MPU2 addressing violation interrupt and protection violation interrupt + CIC: 96 MPU3 addressing violation interrupt and protection violation interrupt + */ + KeyStone_CIC_event_map(gpCIC_regs, 90, gCIC_EXC_out_num); + KeyStone_CIC_event_map(gpCIC_regs, 92, gCIC_EXC_out_num); + KeyStone_CIC_event_map(gpCIC_regs, 94, gCIC_EXC_out_num); + KeyStone_CIC_event_map(gpCIC_regs, 96, gCIC_EXC_out_num); + gCIC_EXC_EN_MASK[2] |= + (1<<(90 -32*2)) + |(1<<(92 -32*2)) + |(1<<(94 -32*2)); + gCIC_EXC_EN_MASK[3] |= + (1<<(96 -32*3)); + + /* 6618_6670 only */ + if(C6670_EVM==DSP_Board_Type + ||DUAL_NYQUIST_EVM==DSP_Board_Type) + { + /* + CIC: 174 MPU4 addressing violation interrupt and protection violation interrupt + CIC: 180 MPU5 addressing violation interrupt and protection violation interrupt + */ + KeyStone_CIC_event_map(gpCIC_regs, 174, gCIC_EXC_out_num); + KeyStone_CIC_event_map(gpCIC_regs, 180, gCIC_EXC_out_num); + gCIC_EXC_EN_MASK[5] |= + (1<<(174-32*5)) + |(1<<(180-32*5)); + } + } + + if(TCI6614_EVM==DSP_Board_Type) + { + /* route the following system events to CIC out + CIC: 23 MPU0~7 addressing violation interrupt combine output + CIC: 37 MPU0~7 protection violation interrupt combine output + */ + KeyStone_CIC_event_map(gpCIC_regs, 23, gCIC_EXC_out_num); + KeyStone_CIC_event_map(gpCIC_regs, 37, gCIC_EXC_out_num); + gCIC_EXC_EN_MASK[0] |= + (1<<23); + gCIC_EXC_EN_MASK[1] |= + (1<<(37 -32)); + + } + /* ----------- Mapping MPU interrupt for different chips end -----------------------*/ + + /* Enable Global host interrupts. */ + gpCIC_regs->GLOBAL_ENABLE_HINT_REG= 1; + +} +/***************************************************************************** + Prototype : KeyStone_Exception_cfg + Description : Config the system err and external exception to generate the NMI. + Call this function as last step after all + configuration/initialization complete + Input : Bool bGlobalExceptionMaster. If TRUE, the global exception events + from CIC will be routed to exception model of this CPU core. + Output : None + Return Value : +*****************************************************************************/ +void KeyStone_Exception_cfg(Bool bGlobalExceptionMaster) +{ + + puts("Enable Exception handling..."); + + TSCL = 0; /* Enable the TSC */ + + memset(&exception_record, 0, sizeof(exception_record)); +#if 0 + /*Clear all CPU events*/ + gpCGEM_regs->EVTCLR[0]= 0xFFFFFFFF; + gpCGEM_regs->EVTCLR[1]= 0xFFFFFFFF; + gpCGEM_regs->EVTCLR[2]= 0xFFFFFFFF; + gpCGEM_regs->EVTCLR[3]= 0xFFFFFFFF; +#endif + /*clear memory fault*/ + gpCGEM_regs->L1PMPFCR = 1; + gpCGEM_regs->L1DMPFCR = 1; + gpCGEM_regs->L2MPFCR = 1; + gpXMC_regs->XMPFCR = 1; + + /*clear configuration bus error*/ + gpCGEM_regs->ICFGMPFCR= 1; + gpCGEM_regs->ECFGERRCLR= 1; + + /* clear the MDMAERR */ + gpCGEM_regs->MDMAERRCLR = 1; + + /*clear interrupt drop staus*/ + gpCGEM_regs->INTXCLR = 1; + + gpCGEM_regs->INTDMASK= ~IER; /*only monitor drop of enabled interrupts*/ + + /*enable events: + 10 MSMC_mpf_error_n MSMC Memory protection fault caused by local CorePac + 96 INTERR Dropped CPU interrupt event + 97 EMC_IDMAERR Invalid IDMA parameters + 110 MDMAERREVT XMC VBUSM error event + 113 PMC_ED Single bit error detected during DMA accesses L1P + 117 UMC_ED2 Uncorrected bit error detected LL2 + 119 SYS_CMPA CPU Memory Protection Fault for local configuration of INTC and power control + 120 PMC_CMPA CPU memory protection fault for L1P + 121 PMC_DMPA DMA memory protection fault for L1P + 122 DMC_CMPA CPU memory protection fault for L1D (and other memory read finally goes through the L1D controller) + 123 DMC_DMPA DMA memory protection fault for L1D + 124 UMC_CMPA CPU memory protection fault for LL2 + 125 UMC_DMPA DMA memory protection fault for LL2 + 126 EMC_CMPA CPU memory protection fault for other local configuration space between 0x01000000 - 0x01BFFFFF + 127 EMC_BUSERR Bus Error Interrupt for global configuration space between 0x01C00000 - 0x07FFFFFF + */ + gpCGEM_regs->EXPMASK[0]= ~(1<EXPMASK[1]= 0xFFFFFFFF; + gpCGEM_regs->EXPMASK[2]= 0xFFFFFFFF; + gpCGEM_regs->EXPMASK[3]= ~((1<<(CSL_GEM_INTERR - 96))| + (1<<(CSL_GEM_EMC_IDMAERR-96))| + (1<<(CSL_GEM_MDMAERREVT-96))| + (1<<(CSL_GEM_PMC_ED-96))| + (1<<(CSL_GEM_UMC_ED2-96))| + (1<<(CSL_GEM_SYS_CMPA-96))| + (1<<(CSL_GEM_PMC_CMPA-96))| + (1<<(CSL_GEM_PMC_DMPA-96))| + (1<<(CSL_GEM_DMC_CMPA-96))| + (1<<(CSL_GEM_DMC_DMPA-96))| + (1<<(CSL_GEM_UMC_CMPA-96))| + (1<<(CSL_GEM_UMC_DMPA-96))| + (1<<(CSL_GEM_EMC_CMPA-96))| + (1<<(CSL_GEM_EMC_BUSERR-96))); + + + if(bGlobalExceptionMaster) + { + /*enable exception events routed from CIC, + please note, this should be only configured for one CPU*/ + KeyStone_CIC_exception_events_mapping(); + gpCGEM_regs->EXPMASK[guwIntcCICExcEvtIdx>>5] &= (~(1<<(guwIntcCICExcEvtIdx&0x1F))); + } + + /*clear exception flag*/ + ECR = EFR; + IERR = 0; + + /*Eanble external exception, global exception enable*/ + TSR = TSR| + (1<>CSL_CGEM_MDMAERR_ERR_SHIFT; + if (1==err) { + puts(" MDMA read status error detected"); + } + else if (2==err) { + puts(" MDMA write status error detected"); + } + else if (3==err) { + puts(" CFG read status error detected"); + } + else if (4==err) { + puts(" CFG write status error detected"); + } + + printf(" XID (Transaction ID)= %d\n", + (ERR_REG & CSL_CGEM_MDMAERR_XID_MASK)>>CSL_CGEM_MDMAERR_XID_SHIFT); + + stat= (ERR_REG & CSL_CGEM_MDMAERR_STAT_MASK)>>CSL_CGEM_MDMAERR_STAT_SHIFT; + printf(" %s\n", bus_err_stat_str[stat]); +} + +/***************************************************************************** + Prototype : KeyStone_CIC_EXC_handler + Description : This function handle the exception events from CIC + Input : void + Output : None + Return Value : void + + History : + 1.Date : 2012/10/18 + Author : Zhan + Modification : Created function + + 2.Date : 2012/10/28 + Author : Brighton Feng + Modification : Add EDMA error processing + +*****************************************************************************/ +void KeyStone_CIC_EXC_handler() +{ + int i; + Uint32 status[4], status5 = 0; + + TDSP_Board_Type DSP_Board_Type; + + DSP_Board_Type= KeyStone_Get_dsp_board_type(); + + /*Step1: Disable CIC host interrupt*/ + KeyStone_CIC_disable_host_int(gpCIC_regs, gCIC_EXC_out_num); + + status[0]= gpCIC_regs->ENA_STATUS_REG[0]&gCIC_EXC_EN_MASK[0]; + status[1]= gpCIC_regs->ENA_STATUS_REG[1]&gCIC_EXC_EN_MASK[1]; + status[2]= gpCIC_regs->ENA_STATUS_REG[2]&gCIC_EXC_EN_MASK[2]; + status[3]= gpCIC_regs->ENA_STATUS_REG[3]&gCIC_EXC_EN_MASK[3]; + exception_record.status.ext_sts.CIC_STATUS[0]= status[0]; + exception_record.status.ext_sts.CIC_STATUS[1]= status[1]; + exception_record.status.ext_sts.CIC_STATUS[2]= status[2]; + exception_record.status.ext_sts.CIC_STATUS[3]= status[3]; + + /*Step2: clear system events*/ + gpCIC_regs->ENA_STATUS_REG[0]= status[0]; + gpCIC_regs->ENA_STATUS_REG[1]= status[1]; + gpCIC_regs->ENA_STATUS_REG[2]= status[2]; + gpCIC_regs->ENA_STATUS_REG[3]= status[3]; + + /* The different device INTC number is different, if read the non-exist space will + trigger the L1D memory protection error. + */ + if((C6670_EVM == DSP_Board_Type) + ||(DUAL_NYQUIST_EVM == DSP_Board_Type) + ||(TCI6614_EVM == DSP_Board_Type)) + { + status5 = gpCIC_regs->ENA_STATUS_REG[5]&gCIC_EXC_EN_MASK[5]; + exception_record.status.ext_sts.CIC_STATUS[5]= status5; + + /*Step2: clear system events*/ + gpCIC_regs->ENA_STATUS_REG[5]= status5 ; + } + + /*----------------------------EDMA error-----------------------------*/ + /* + CIC: 0 EDMA3CC1 EDMACC_ERRINT EDMA3CC1 error interrupt + CIC: 2 EDMA3CC1 EDMATC_ERRINT0 EDMA3CC1 EDMA3TC0 error interrupt + CIC: 3 EDMA3CC1 EDMATC_ERRINT1 EDMA3CC1 EDMA3TC1 error interrupt + CIC: 4 EDMA3CC1 EDMATC_ERRINT2 EDMA3CC1 EDMA3TC2 error interrupt + CIC: 5 EDMA3CC1 EDMATC_ERRINT3 EDMA3CC1 EDMA3TC3 error interrupt*/ + if(status[0]&0x3D) + EDMA_error_handler(1, status[0]&0x3D); + + /* + CIC: 16 EDMA3CC2 EDMACC_ERRINT EDMA3CC2 error interrupt + CIC: 18 EDMA3CC2 EDMATC_ERRINT0 EDMA3CC2 EDMA3TC0 error interrupt + CIC: 19 EDMA3CC2 EDMATC_ERRINT1 EDMA3CC2 EDMA3TC1 error interrupt + CIC: 20 EDMA3CC2 EDMATC_ERRINT2 EDMA3CC2 EDMA3TC2 error interrupt + CIC: 21 EDMA3CC2 EDMATC_ERRINT3 EDMA3CC2 EDMA3TC3 error interrupt*/ + if((status[0]>>16)&0x3D) + EDMA_error_handler(2, (status[0]>>16)&0x3D); + + /* + CIC: 32 EDMA3CC0 EDMACC_ERRINT EDMA3CC0 error interrupt + CIC: 34 EDMA3CC0 EDMATC_ERRINT0 EDMA3CC0 EDMA3TC0 error interrupt + CIC: 35 EDMA3CC0 EDMATC_ERRINT1 EDMA3CC0 EDMA3TC1 error interrupt*/ + if(status[1]&0xD) + EDMA_error_handler(0, status[1]&0xD); + + /*----------------------------MPU error-----------------------------*/ + if(TCI6614_EVM == DSP_Board_Type) + { + //CIC: 23 MPU0~7 addressing violation interrupt combine output + //CIC: 37 MPU0~7 protection violation interrupt combine output + if((status[0]&(1<<23))||(status[1]&(1<<(37-32)))) + { + for(i=0; i<8; i++) + { + /*MPU5 (for BCP) of TCI6614 is only accessible + when BCP is enabled through PSC*/ + if((5==i)&& + ((CSL_PSC_getPowerDomainState(5) != PSC_PDSTATE_ON) || + (CSL_PSC_getModuleState (12) != PSC_MODSTATE_ENABLE))) + continue; + + if(gpMPU_regs[i]->INT_RAW_STATUS_SET & 0x3) + { + KeyStone_peripherals_MPU_excepiton_handler(i); + } + } + + /*The MPU events in TCI6614 are different from other KeyStone + devices. All the MPU0~7 events are combined into single event + and connected to the CIC0 as one system event. + We have to clear the MPU event flag at the source level first + and then are able to clear the CIC flags because the INTD for the + MPU events is for the combination purpose but do not convert + the level interrupt to pulse.*/ + /*clear system events*/ + gpCIC_regs->ENA_STATUS_REG[0]= status[0]; + gpCIC_regs->ENA_STATUS_REG[1]= status[1]; + } + } + else + { + //CIC: 90 MPU0 addressing violation interrupt and protection violation interrupt + if(status[2]&(1<<(90-64))) + { + KeyStone_peripherals_MPU_excepiton_handler(0); + } + //CIC: 92 MPU1 addressing violation interrupt and protection violation interrupt + if(status[2]&(1<<(92-64))) + { + KeyStone_peripherals_MPU_excepiton_handler(1); + } + //CIC: 94 MPU2 addressing violation interrupt and protection violation interrupt + if(status[2]&(1<<(94-64))) + { + KeyStone_peripherals_MPU_excepiton_handler(2); + } + //CIC: 96 MPU3 addressing violation interrupt and protection violation interrupt + if(status[3]&(1<<(96-96))) + { + KeyStone_peripherals_MPU_excepiton_handler(3); + } + + if((C6670_EVM == DSP_Board_Type) + ||(DUAL_NYQUIST_EVM == DSP_Board_Type)) + { + //CIC: 174 MPU4 addressing violation interrupt and protection violation interrupt + //CIC: 180 MPU5 addressing violation interrupt and protection violation interrupt + if(status5&(1<<(174-160))) + { + KeyStone_peripherals_MPU_excepiton_handler(4); + } + if(status5&(1<<(180-160))) + { + KeyStone_peripherals_MPU_excepiton_handler(5); + } + } + } + + /*----------------------------MSMC error-----------------------------*/ + //CIC: 99 MSMC_dedc_nc_error Non-correctable (2-bit) soft error detected on SRAM read + if(status[3]&(1<<(99-96))) + { + KeyStone_SL2_EDC_handler(); + } + //CIC: 100 MSMC_scrub_nc_error Non-correctable (2-bit) soft error detected during scrub cycle + if(status[3]&(1<<(100-96))) + { + KeyStone_SL2_EDC_handler(); + } + + /* + CIC: 102 MSMC_mpf_error8 Memory protection fault indicators for each system master PrivID + CIC: 103 MSMC_mpf_error9 Memory protection fault indicators for each system master PrivID + CIC: 104 MSMC_mpf_error10 Memory protection fault indicators for each system master PrivID + CIC: 105 MSMC_mpf_error11 Memory protection fault indicators for each system master PrivID + CIC: 106 MSMC_mpf_error12 Memory protection fault indicators for each system master PrivID + CIC: 107 MSMC_mpf_error13 Memory protection fault indicators for each system master PrivID + CIC: 108 MSMC_mpf_error14 Memory protection fault indicators for each system master PrivID + CIC: 109 MSMC_mpf_error15 Memory protection fault indicators for each system master PrivID*/ + if((status[3]>>(102-96))&0xFF) + KeyStone_MSMC_protection_exception_handler(); + + if((C6670_EVM == DSP_Board_Type) + ||(DUAL_NYQUIST_EVM == DSP_Board_Type) + ||(TCI6614_EVM == DSP_Board_Type)) + { + /* + CIC: 170 MSMC_mpf_error4 Memory protection fault indicators for each system master PrivID + CIC: 171 MSMC_mpf_error5 Memory protection fault indicators for each system master PrivID + CIC: 172 MSMC_mpf_error6 Memory protection fault indicators for each system master PrivID + CIC: 173 MSMC_mpf_error7 Memory protection fault indicators for each system master PrivID*/ + if((status5>>(170-160))&0xF) + KeyStone_MSMC_protection_exception_handler(); + + } + + /*----------------------------DDR ECC error-------------------------*/ + //CIC: 110 DDR3_ERR DDR3_EMIF Error Interrupt + if(status[3]&(1<<(110-96))) + { + printf(" DDR ECC error happened during "); + + exception_record.status.ext_sts.info.memory.fault_status.DDR_IRQSTATUS_SYS= + gpDDR_regs->IRQSTATUS_SYS; + + if(gpDDR_regs->IRQSTATUS_SYS&CSL_EMIF4F_IRQSTATUS_SYS_REG_RD_ECC_ERR_SYS_MASK) + printf("read "); + if(gpDDR_regs->IRQSTATUS_SYS&CSL_EMIF4F_IRQSTATUS_SYS_REG_WR_ECC_ERR_SYS_MASK) + printf("write "); + printf(".\n"); + + //clear the status + gpDDR_regs->IRQSTATUS_SYS= CSL_EMIF4F_IRQSTATUS_SYS_REG_RD_ECC_ERR_SYS_MASK + |CSL_EMIF4F_IRQSTATUS_SYS_REG_WR_ECC_ERR_SYS_MASK; + } + + /*Step3: Enable the CIC host interrupt */ + KeyStone_CIC_enable_host_int(gpCIC_regs, gCIC_EXC_out_num); + +} + +/***************************************************************************** + Prototype : KeyStone_EXC_external + Description : external exception processing + Input : void + Output : None + Return Value : + + History : + 1.Date : 2010/12/12 + Author : Brighton Feng + Modification : Created function +*****************************************************************************/ +void KeyStone_EXC_external(void) +{ + int i; + unsigned int INTXSTAT, flag[4]; + + for(i= 0; i<4; i++) + { + flag[i] = gpCGEM_regs->MEXPFLAG[i]; + if(flag[i]) + { + exception_record.status.ext_sts.MEXPFLAG[i]= flag[i]; + printf("External exception happened. MEXPFLAG[%d]=0x%x.\n", + i, flag[i]); + gpCGEM_regs->EVTCLR[i] = flag[i]; + } + } + + if(0 == (flag[0]|flag[1]|flag[2]|flag[3])) + { + puts("Enter external Exception service routine, but external excpetion flage is 0!"); + return; + } + + /*Exception events routed from CIC*/ + if(flag[guwIntcCICExcEvtIdx>>5] & (1<<(guwIntcCICExcEvtIdx&0x1F))) + { + KeyStone_CIC_EXC_handler(); + } + + /*MSMC memory protection exception*/ + if(flag[0]&(1<INTXSTAT; + exception_record.status.ext_sts.info.INTXSTAT= INTXSTAT; + + if(INTXSTAT&CSL_CGEM_INTXSTAT_DROP_MASK) + printf(" Event 96: DSP Interrupt %d (INTC input Event %d) dropped\n", + (INTXSTAT&CSL_CGEM_INTXSTAT_CPUINT_MASK)>>CSL_CGEM_INTXSTAT_CPUINT_SHIFT, + (INTXSTAT&CSL_CGEM_INTXSTAT_SYSINT_MASK)>>CSL_CGEM_INTXSTAT_SYSINT_SHIFT); + } + + if(flag[3]&(1<<(CSL_GEM_EMC_IDMAERR-96))) + puts(" Event 97: EMC_IDMAERR Invalid IDMA parameters"); + + /*MDMA XMC VBUSM error*/ + if(flag[3]&(1<<(CSL_GEM_MDMAERREVT-96))) + { + puts(" Event 110: MDMAERREVT XMC VBUSM error event"); + if(gpXMC_regs->XMPFSR) + { + /*XMC protection error*/ + memory_protection_exception_handler(gpXMC_regs->XMPFAR, gpXMC_regs->XMPFSR); + gpXMC_regs->XMPFCR = 1; + } + else + { + /*other VBUSM error*/ + Bus_error_handler(gpCGEM_regs->MDMAERR); + } + /* clear the MDMAERR */ + gpCGEM_regs->MDMAERRCLR = 1; + } + + /*L1P Single bit error detected during DMA read*/ + if(flag[3]&(1<<(CSL_GEM_PMC_ED-96))) + { + puts(" Event 113: PMC_ED Single bit error detected during DMA read"); + L1P_ED_handler(); + } + + /*LL2 Uncorrected bit error detected*/ + if(flag[3]&(1<<(CSL_GEM_UMC_ED2-96))) + { + puts(" Event 117: UMC_ED2 Uncorrected bit error detected"); + LL2_EDC_handler(FALSE); + } + + /*local register memory protection exception*/ + if(flag[3]&(1<<(CSL_GEM_SYS_CMPA-96))) + { + puts(" Event 119: SYS_CMPA CPU Memory Protection Fault for local configuration of INTC and power control"); + } + + /*L1P memory protection exception*/ + if(flag[3]&(3<<(CSL_GEM_PMC_CMPA-96))) + { + if(flag[3]&(1<<(CSL_GEM_PMC_CMPA-96))) + puts(" Event 120: PMC_CMPA CPU memory protection fault for L1P"); + if(flag[3]&(1<<(CSL_GEM_PMC_DMPA-96))) + puts(" Event 121: PMC_DMPA DMA memory protection fault for L1P"); + memory_protection_exception_handler(gpCGEM_regs->L1PMPFAR, gpCGEM_regs->L1PMPFSR); + gpCGEM_regs->L1PMPFCR = 1; + } + + /*L1D memory protection exception*/ + if(flag[3]&(3<<(CSL_GEM_DMC_CMPA-96))) + { + if(flag[3]&(1<<(CSL_GEM_DMC_CMPA-96))) + puts(" Event 122: DMC_CMPA CPU memory protection fault for L1D (and other memory read finally goes through the L1D controller)"); + if(flag[3]&(1<<(CSL_GEM_DMC_DMPA-96))) + puts(" Event 123: DMC_DMPA DMA memory protection fault for L1D"); + memory_protection_exception_handler(gpCGEM_regs->L1DMPFAR, gpCGEM_regs->L1DMPFSR); + gpCGEM_regs->L1DMPFCR = 1; + } + + /*LL2 memory protection exception*/ + if(flag[3]&(3<<(CSL_GEM_UMC_CMPA-96))) + { + if(flag[3]&(1<<(CSL_GEM_UMC_CMPA-96))) + puts(" Event 124: UMC_CMPA CPU memory protection fault for L2 "); + if(flag[3]&(1<<(CSL_GEM_UMC_DMPA-96))) + puts(" Event 125: UMC_DMPA DMA memory protection fault for L2 "); + memory_protection_exception_handler(gpCGEM_regs->L2MPFAR, gpCGEM_regs->L2MPFSR); + gpCGEM_regs->L2MPFCR = 1; + } + + /*local registers protection exception*/ + if(flag[3]&(1<<(CSL_GEM_EMC_CMPA-96))) + { + puts(" Event 126: EMC_CMPA CPU memory protection fault for local configuration space between 0x01000000-0x01BFFFFF"); + memory_protection_exception_handler(gpCGEM_regs->ICFGMPFAR, gpCGEM_regs->ICFGMPFSR); + gpCGEM_regs->ICFGMPFCR= 1; + } + + /*external configuration bus error*/ + if(flag[3]&(Uint32)(1<<(CSL_GEM_EMC_BUSERR-96))) + { + puts(" Event 127: EMC_BUSERR Bus Error Interrupt for global configuration space between 0x01C00000 - 0x07FFFFFF"); + Bus_error_handler(gpCGEM_regs->ECFGERR); + gpCGEM_regs->ECFGERRCLR= 1; + } +} + +char * internal_exception_str[]= +{ + "Instruction fetch exception", + "Fetch packet exception", + "Execute packet exception", + "Opcode exception", + "Resource conflict exception", + "Resource access exception", + "Privilege exception", + "SPLOOP buffer exception", + "Missed stall exception" +}; + +/***************************************************************************** + Prototype : EXC_internal + Description : internal exception handler + Input : void + Output : None + Return Value : + + History : + 1.Date : 2010/12/12 + Author : Brighton Feng + Modification : Created function + +*****************************************************************************/ +/*internal exception handler*/ +void EXC_internal(void) +{ + int i; + unsigned int ierr; + + /*record IERR */ + ierr = IERR; + exception_record.status.IERR= ierr; + + if(ierr) + { + /*Clear internal excpeiton flag*/ + IERR= 0; + + printf("internal excpetion happened. IERR=0x%x.\n", ierr); + for(i=0; i<9; i++) + { + if((ierr>>i)&1) + printf(" %s\n", internal_exception_str[i]); + } + if (ierr & CSL_CHIP_IERR_IFX_MASK) { + /* L1P EDC Processing*/ + L1P_ED_handler(); + } + } + else + puts("Enter Internal Exception service routine, but internal excpetion flage is 0!"); + +} +/***************************************************************************** + Prototype : EXC_nmi + Description : NMI processing + Input : void + Output : None + Return Value : + + History : + 1.Date : 2010/12/12 + Author : Brighton Feng + Modification : Created function + +*****************************************************************************/ +void EXC_NMI(void) +{ + puts("NMI exception happened, normally you should reset the DSP to recover from the problem!"); +} + +/***************************************************************************** + Prototype : EXC_swgen + Description : software generated exception handler + Input : void + Output : None + Return Value : +*****************************************************************************/ +void EXC_swgen(void) +{ + puts("Software generated exception happened."); +} + +/***************************************************************************** + Prototype : Exception_service_routine + Description : Exception service routine + Input : void + Output : None + Return Value : + + History : + 1.Date : 2010/12/12 + Author : Brighton Feng + Modification : Created function + +*****************************************************************************/ +#pragma NMI_INTERRUPT( Exception_service_routine ); +void Exception_service_routine(void) +{ + unsigned int efr, nrp, ntsr, tscl, tsch, irp, itsr; + + /*record timestamp*/ + tscl = TSCL; + exception_record.TSCL= tscl; + tsch = TSCH; + exception_record.TSCH= tsch; + + nrp = NRP; /*record NRP */ + exception_record.NRP= nrp; + ntsr = NTSR; /*record NTSR */ + exception_record.NTSR= ntsr; + efr = EFR; /*record EFR */ + exception_record.EFR= efr; + + irp = IRP; /*record IRP */ + itsr = ITSR; /*record ITSR */ + exception_record.IRP= irp; + exception_record.ITSR= itsr; + + if(efr) + { + /*Clear excpeiton flag*/ + ECR = efr; + + /*check all possible exceptions*/ + if (efr & CSL_CHIP_EFR_OXF_MASK) { + /* S/W generated exception */ + EXC_swgen(); + } + if (efr & CSL_CHIP_EFR_IXF_MASK) { + /* internal exception */ + EXC_internal(); + } + if (efr & CSL_CHIP_EFR_EXF_MASK) { + /* external exception */ + KeyStone_EXC_external(); + } + if (efr & CSL_CHIP_EFR_NXF_MASK) { + /* legacy NMI exception */ + EXC_NMI(); + } + } + else + puts("Enter Exception service routine, but excpetion flage is 0!"); + + printf("NRP=0x%x, NTSR=0x%x, IRP=0x%x, ITSR=0x%x, TSCH= 0x%x, TSCL= 0x%x\n", + nrp, ntsr, irp, itsr, tsch, tscl); + + printf(" B3=0x%x, A4=0x%x, B4= 0x%x, B14= 0x%x, B15= 0x%x\n", + exception_record.B3, exception_record.A4, + exception_record.B4, exception_record.B14, + exception_record.B15); + + /* + It is not always possible to safely exit the exception handling routine. Conditions that + can prevent a safe return from exceptions include: + 1. SPLOOPs that are terminated by an exception cannot be resumed correctly. The + SPLX bit in NTSR should be verified to be 0 before returning. + 2. Exceptions that occur when interrupts are blocked cannot be resumed correctly. + The IB bit in NTSR should be verified to be 0 before returning. + 3. Exceptions that occur at any point in the code that cannot be interrupted safely + (for example, a tight loop containing multiple assignments) cannot be safely + returned to. The compiler will normally disable interrupts at these points in the + program; check the GIE bit in NTSR to be 1 to verify that this condition is met. + 4. NRP is not in valid address space*/ + if((ntsr&CSL_CHIP_TSR_SPLX_MASK) + ||(ntsr&CSL_CHIP_TSR_IB_MASK) + ||(0==(ntsr&CSL_CHIP_TSR_GIE_MASK)) + ||(0x800000>NRP)) + { + puts("Exception happened at a place can not safely return!"); + //while(1); //trap + exit(0); + } + +} + +/***************************************************************************** + Prototype : Nested_Exception_service_routine + Description : Nested Exception service routine + When a non-maskable exception happens in the first exception service routine, + then the reset vector is used when redirecting program execution to service the second + exception. In this case, NTSR and NRP are left unchanged. TSR is copied to ITSR and + the current PC is copied to IRP. TSR is set to the default exception processing value and + the NMIE bit in IER is cleared in this case preventing any further external exceptions. + Input : void + Output : None + Return Value : + + History : + 1.Date : 2010/12/29 + Author : Brighton Feng + Modification : Created function + +*****************************************************************************/ +interrupt void Nested_Exception_service_routine(void) +{ + unsigned int tscl, tsch; + + /*record timestamp*/ + tscl = TSCL; + tsch = TSCH; + + if(0==exception_record.TSCL) + exception_record.TSCL= tscl; + if(0==exception_record.TSCH) + exception_record.TSCH= tsch; + if(0==exception_record.NRP) + exception_record.NRP= NRP; + if(0==exception_record.NTSR) + exception_record.NTSR= NTSR; + if(0==exception_record.EFR) + exception_record.EFR= EFR; + if(0==exception_record.status.IERR) + exception_record.status.IERR= IERR; + + exception_record.IRP= IRP; + exception_record.ITSR= ITSR; + + printf("Nested exception happened! IRP=0x%x, ITSR=0x%x\n", + IRP, ITSR); + + printf("NRP=0x%x, NTSR=0x%x, EFR=0x%x, IERR=0x%x, TSCH= 0x%x, TSCL= 0x%x\n", + NRP, NTSR, EFR, IERR, tsch, tscl); + + while(1); //trap +// exit(0); +} + +/*=========================other utility functions==========================*/ +/*clear all interrupt flag/status, setup ISTP to begining of LL2*/ +void CPU_interrupt_init() +{ + //clear interrupt and excpetion events + ICR = IFR; + ECR = EFR; + IER= 3; //disable all interrupts + + /* disable event combine */ + gpCGEM_regs->EVTMASK[0] = 0xffffffff; + gpCGEM_regs->EVTMASK[1] = 0xffffffff; + gpCGEM_regs->EVTMASK[2] = 0xffffffff; + gpCGEM_regs->EVTMASK[3] = 0xffffffff; + + /*Clear all CPU events*/ + gpCGEM_regs->EVTCLR[0]= 0xFFFFFFFF; + gpCGEM_regs->EVTCLR[1]= 0xFFFFFFFF; + gpCGEM_regs->EVTCLR[2]= 0xFFFFFFFF; + gpCGEM_regs->EVTCLR[3]= 0xFFFFFFFF; + + /*Interrupt Service Table Pointer to begining of LL2 memory*/ + ISTP= 0x800000; +} + +/*enable interrupt to CPU: IER |= uiIER_en_mask; GIE=1*/ +void CPU_interrupt_enable(Uint32 uiIER_en_mask) +{ + ICR= uiIER_en_mask; + IER |= uiIER_en_mask; + + //enable GIE + //TSR = TSR|1; +} + +/***************************************************************************** + Prototype : KeyStone_get_device_info + Description : Get device information + Input : None + Output : None + Return Value : + + History : + 1.Date : 2010/12/12 + Author : Brighton Feng + Modification : Created function + 2.Date : 2014/12/2 + Author : Brighton Feng + Modification : Update to parser device type, boot mode, endian information, + speed grade, required CVDD + +*****************************************************************************/ +//get device speed grade from the EFUSE register +void KeyStone_get_device_speed_grade() +{ + Uint32 uiDevSpeed, uiSpeedCode; + + uiSpeedCode= (DEVSPEED&DEVSPEED_DSP_SPEED_MASK)>>DEVSPEED_DSP_SPEED_SHIFT; + + if(uiSpeedCode&DEVSPEED_800_MHZ_MASK_H) uiDevSpeed= 800; + else if(uiSpeedCode&DEVSPEED_1000_MHZ_MASK_H) uiDevSpeed= 1000; + else if(uiSpeedCode&DEVSPEED_1200_MHZ_MASK_H) uiDevSpeed= 1200; + else if(uiSpeedCode&DEVSPEED_1250_MHZ_MASK_H) uiDevSpeed= 1250; + else if(uiSpeedCode&DEVSPEED_1400_MHZ_MASK_H) uiDevSpeed= 1400; + else if(uiSpeedCode&DEVSPEED_1400_MHZ_MASK_L) uiDevSpeed= 1400; + else if(uiSpeedCode&DEVSPEED_1250_MHZ_MASK_L) uiDevSpeed= 1250; + else if(uiSpeedCode&DEVSPEED_1200_MHZ_MASK_L) uiDevSpeed= 1200; + else if(uiSpeedCode&DEVSPEED_1000_MHZ_MASK_L) uiDevSpeed= 1000; + else uiDevSpeed= 800; + + printf("Device speed grade = %dMHz.\n", uiDevSpeed); +} + +char * device_type_str[]= +{ + "TCI6616", + "C6670/TCI6618", + "C6678/TCI6608", + "TCI6614", + "unknown" +}; +char * endian_str[]= +{ + "big", + "little" +}; +char * boot_mode_str[]= +{ + "No boot or EMIF16(NOR FLASH) or UART", + "Serial Rapid I/O", + "Ethernet (SGMII)", + "Ethernet (SGMII) or NAND FLASH", + "PCIE", + "I2C", + "SPI", + "HyperLink" + }; +char * input_clk_str[]= +{ + "50MHz", + "66.67MHz", + "80MHz", + "100MHz", + "156.25MHz", + "250MHz", + "312.5MHz", + "122.88MHz", + "bypassed" +}; +void KeyStone_get_device_info() +{ + char * boot_mode; + Uint8 ucBootMode, ucBootMaster; + Uint32 uiVID; + Uint8 ucPLL_cfg= 8; //8 means bypassed + Uint32 * DieID= (Uint32 *)&gpBootCfgRegs->DIE_ID_REG0; + Uint32 uiJTAG_ID = gpBootCfgRegs->DEVICE_ID_REG0; + Uint32 uiDevStat = gpBootCfgRegs->BOOT_REG0; + + gDSP_board_type=KeyStone_Get_dsp_board_type(); + + ucBootMode= (uiDevStat&DEVSTAT_BOOTMODE_MASK)>>DEVSTAT_BOOTMODE_SHIFT; + ucBootMaster= (uiDevStat&DEVSTAT_BOOTMASTER_MASK)>>DEVSTAT_BOOTMASTER_SHIFT; + + if((TCI6614_EVM==gDSP_board_type)&&(1==ucBootMaster)) + { + boot_mode= "ARM"; //ARM boot + } + else + boot_mode= boot_mode_str[ucBootMode]; + + //PLL is not configured with SPI and I2C master boot mode + if((5!=ucBootMode)&&(6!=ucBootMode)) + ucPLL_cfg= (uiDevStat&DEVSTAT_SYSPLL_MASK)>>DEVSTAT_SYSPLL_SHIFT; + + printf("JTAG ID= 0x%08x. This is %s device, version variant = %d.\n", uiJTAG_ID, + device_type_str[gDSP_board_type], uiJTAG_ID>>28); + + printf("DEVSTAT= 0x%08x. %s endian, %s boot, PLL configuration implies the input clock for core is %s.\n", + uiDevStat, endian_str[uiDevStat&DEVSTAT_LENDIAN_MASK], boot_mode, + input_clk_str[ucPLL_cfg]); + + uiVID= (gpPSC_regs->VCNTLID&CSL_PSC_VCNTLID_VCNTL_MASK)>>CSL_PSC_VCNTLID_VCNTL_SHIFT; + printf("SmartReflex VID= %d, required core voltage= %.3fV.\n", uiVID, 0.7+(float)uiVID*0.41/64.f); + + printf("Die ID= 0x%08x, 0x%08x, 0x%08x, 0x%08x\n", DieID[0], DieID[1], DieID[2], DieID[3]); + + KeyStone_get_device_speed_grade(); +} +/***************************************************************************** + Prototype : KeyStone_common_device_init + Description : common initialization for internal modules in K2 device + enable memory protection interrupts, EDC for MSMC RAM + History : + 1.Date : July 11, 2014 + Author : Brighton Feng + Modification : Created function +*****************************************************************************/ +void KeyStone_common_device_init() +{ + int i; + KeyStone_get_device_info(); + + /* enable common MPU interrupts */ + for(i=0; i<4; i++) + { + KeyStone_MPU_interrupt_enable(i); + } + + /*Enable MSMC EDC and setup scrubbing cycle counter= 255*1024*/ + KeyStone_SL2_EDC_enable(255); +} + +/***************************************************************************** + Prototype : KeyStone_common_CPU_init + Description : common initialization for internal modules in K2 device + enable TSC, EDC for local RAM; clear cache; protect L1 as cache + History : + 1.Date : September 1, 2014 + Author : Brighton Feng + Modification : Created function +*****************************************************************************/ +void KeyStone_common_CPU_init() +{ + TSC_init(); //initialize TSC to measure cycle + + /*clear all interrupt flag/status, setup ISTP to begining of LL2*/ + CPU_interrupt_init(); + + /*clean cache from previous run, not required from power on or cold reset*/ + CACHE_wbInvAllL2(CACHE_WAIT); + CSL_XMC_invalidatePrefetchBuffer(); + _mfence(); + _mfence(); + + /* protect L1 as cache */ + L1_cache_protection(); + + //Enable MSMC Memory protection error interrupt for local core, refer to MSMC user guide section3.8 + // KeyStone_MSMC_MP_interrupt_en(1< +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/*----------------------PLL registers definition----------------*/ +#define PLLCTL0_PLLD_SHIFT (0) +#define PLLCTL0_PLLD_MASK (0x3F<>4) | 0x80000000) + +/*max number in two numbers*/ +#define MAX(a, b) (a>b?a:b) +/*min number in two numbers*/ +#define MIN(a, b) (a0xFFFF*4) + byteCnt= 0xFFFF*4; + if((Uint32)blockPtr>=0x0C000000&&(Uint32)blockPtr<0x0D000000) //SL2 + { + CACHE_invL1d((void *)blockPtr, byteCnt, CACHE_WAIT); + CSL_XMC_invalidatePrefetchBuffer(); + } + else if((Uint32)blockPtr>=0x10000000) //DDR or other cores + { + CACHE_invL2((void *)blockPtr, byteCnt, CACHE_WAIT); + CSL_XMC_invalidatePrefetchBuffer(); + } + _mfence(); + _mfence(); + +#if CACHE_DISABLE_INT +/*workaround for the "L2 Cache Corruption During Block and Global Coherence Operations +Issue" described in errata of some devices*/ + asm(" nop 8"); + asm(" nop 8"); + _restore_interrupts(uiOldGIE); //restore interrupt +#endif +} + +static inline void WritebackCache(void * blockPtr, Uint32 byteCnt) +{ + if(byteCnt>0xFFFF*4) + byteCnt= 0xFFFF*4; + if((Uint32)blockPtr>=0x0C000000&&(Uint32)blockPtr<0x0D000000) //SL2 + { + CACHE_wbL1d((void *)blockPtr, byteCnt, CACHE_WAIT); + } + else if((Uint32)blockPtr>=0x10000000) //DDR or other cores + { + CACHE_wbL2((void *)blockPtr, byteCnt, CACHE_WAIT); + } + _mfence(); + _mfence(); +} + +static inline void WritebackAllCache(void * blockPtr) +{ + if((Uint32)blockPtr>=0x0C000000&&(Uint32)blockPtr<0x0D000000) //SL2 + { + CACHE_wbAllL1d(CACHE_WAIT);; + } + else if((Uint32)blockPtr>=0x10000000) //DDR or other cores + { + CACHE_wbAllL2(CACHE_WAIT); + } + _mfence(); + _mfence(); +} + +static inline void WritebackInvalidCache(void * blockPtr, Uint32 byteCnt) +{ +#if CACHE_DISABLE_INT +/*workaround for the "L2 Cache Corruption During Block and Global Coherence Operations +Issue" described in errata of some devices*/ + Uint32 uiOldGIE= _disable_interrupts(); +#endif + + if(byteCnt>0xFFFF*4) + byteCnt= 0xFFFF*4; + if((Uint32)blockPtr>=0x0C000000&&(Uint32)blockPtr<0x0D000000) //SL2 + { + CACHE_wbInvL1d((void *)blockPtr, byteCnt, CACHE_WAIT); + CSL_XMC_invalidatePrefetchBuffer(); + } + else if((Uint32)blockPtr>=0x10000000) //DDR or other cores + { + CACHE_wbInvL2((void *)blockPtr, byteCnt, CACHE_WAIT); + CSL_XMC_invalidatePrefetchBuffer(); + } + _mfence(); + _mfence(); + +#if CACHE_DISABLE_INT +/*workaround for the "L2 Cache Corruption During Block and Global Coherence Operations +Issue" described in errata of some devices*/ + asm(" nop 8"); + asm(" nop 8"); + _restore_interrupts(uiOldGIE); //restore interrupt +#endif +} + +static inline void WritebackInvalidAllCache(void * blockPtr) +{ +#if CACHE_DISABLE_INT +/*workaround for the "L2 Cache Corruption During Block and Global Coherence Operations +Issue" described in errata of some devices*/ + Uint32 uiOldGIE= _disable_interrupts(); +#endif + + if((Uint32)blockPtr>=0x0C000000&&(Uint32)blockPtr<0x0D000000) //SL2 + { + CACHE_wbInvAllL1d(CACHE_WAIT);//CACHE_invL1d((void *)blockPtr, byteCnt, CACHE_WAIT); + CSL_XMC_invalidatePrefetchBuffer(); + } + else if((Uint32)blockPtr>=0x10000000) //DDR or other cores + { + //CACHE_invL2((void *)blockPtr, byteCnt, CACHE_WAIT); + CACHE_wbInvAllL2(CACHE_WAIT); + CSL_XMC_invalidatePrefetchBuffer(); + } + _mfence(); + _mfence(); + +#if CACHE_DISABLE_INT +/*workaround for the "L2 Cache Corruption During Block and Global Coherence Operations +Issue" described in errata of some devices*/ + asm(" nop 8"); + asm(" nop 8"); + _restore_interrupts(uiOldGIE); //restore interrupt +#endif +} + +static inline unsigned int SWAP_ENDIAN(unsigned int byte_index) +{ +#ifdef _BIG_ENDIAN + return ((byte_index&0xFFFFFFFC)+(3-byte_index&3)); +#else + return byte_index; +#endif +} + +static inline void KeyStone_CIC_clear_system_event(CSL_CPINTCRegs* cpIntcRegs, + int input_event_num) +{ + volatile Uint32 dummy_value; + + /*clear input interrupts events*/ + cpIntcRegs->STATUS_CLR_INDEX_REG= input_event_num; + + /*dummy read to make sure the previous write data land into the register*/ + dummy_value= cpIntcRegs->STATUS_CLR_INDEX_REG; +} + +static inline void KeyStone_CIC_disable_host_int(CSL_CPINTCRegs* cpIntcRegs, + int host_int_num) +{ + volatile Uint32 dummy_value; + + /* Disable the host interrupt */ + cpIntcRegs->HINT_ENABLE_CLR_INDEX_REG = host_int_num; + + /*dummy read to make sure the previous write data land into the register*/ + dummy_value= cpIntcRegs->HINT_ENABLE_CLR_INDEX_REG; +} + +static inline void KeyStone_CIC_enable_host_int(CSL_CPINTCRegs* cpIntcRegs, + int host_int_num) +{ + volatile Uint32 dummy_value; + + /* Enable the host interrupt */ + cpIntcRegs->HINT_ENABLE_SET_INDEX_REG = host_int_num; + + /*dummy read to make sure the previous write data land into the register*/ + dummy_value= cpIntcRegs->HINT_ENABLE_SET_INDEX_REG; +} + +static inline void KeyStone_CIC_event_map(CSL_CPINTCRegs* cpIntcRegs, + int input_event_num, int out_num) +{ + /*Map input event to output*/ + cpIntcRegs->CH_MAP[SWAP_ENDIAN(input_event_num)]= out_num; + + /*clear input interrupts events*/ + cpIntcRegs->STATUS_CLR_INDEX_REG= input_event_num; + + /*enable input interrupts events*/ + cpIntcRegs->ENABLE_SET_INDEX_REG= input_event_num; + + /*enable output*/ + cpIntcRegs->HINT_ENABLE_SET_INDEX_REG= out_num; +} + + +typedef enum +{ + DUAL_NYQUIST_EVM = 0, + C6670_EVM, + C6678_EVM, + TCI6614_EVM, + C6657_EVM, + UNKNOWN +}TDSP_Board_Type; + +extern TDSP_Board_Type gDSP_board_type; + +static inline TDSP_Board_Type KeyStone_Get_dsp_board_type() +{ + Uint32 deviceID= gpBootCfgRegs->DEVICE_ID_REG0&0x0FFFFFFF; + + gDSP_board_type= UNKNOWN; + if(0x0009D02F == deviceID) + gDSP_board_type= DUAL_NYQUIST_EVM; + if(0x0B94102F == deviceID) + { + gDSP_board_type= C6670_EVM; + //DSP_Board_Type= DUAL_NYQUIST_EVM; + } + if(0x0009E02F == deviceID) + gDSP_board_type= C6678_EVM; + if(0x0B96202F == deviceID) + gDSP_board_type= TCI6614_EVM; + if(0x0B97A02F == deviceID) + gDSP_board_type= C6657_EVM; + + return gDSP_board_type; +} + +static inline Uint32 KeyStone_Get_DSP_Number() +{ + TDSP_Board_Type DSP_Board_Type= KeyStone_Get_dsp_board_type(); + + if(DUAL_NYQUIST_EVM==DSP_Board_Type) + { + /*Nyquist EVM use boot configure pin 4 and 5 to identify DSPs*/ + return (( gpBootCfgRegs->BOOT_REG0 >> (3+1) ) & 0x03); + } + + /*if use DNUM to differentiate DSPs for two DSPs test, + the program must be run on core 0 of DSP 0 and core 1 of DSP1*/ + return DNUM; +} + +/*clear all interrupt flag/status, setup ISTP to begining of LL2*/ +extern void CPU_interrupt_init(); +/*enable interrupt to CPU: IER |= uiIER_en_mask; GIE=1*/ +extern void CPU_interrupt_enable(Uint32 uiIER_en_mask); + +//get device speed grade from the EFUSE register +extern void KeyStone_get_device_speed_grade(); + +/*Get device information including device type, boot mode, endian information, +speed grade, required voltage...*/ +extern void KeyStone_get_device_info(); + +/*common initialization for internal modules in K2 device. +enable memory protection interrupts, EDC for MSMC RAM*/ +extern void KeyStone_common_device_init(); + +/* enable TSC, EDC for local RAM; clear cache; protect L1 as cache */ +extern void KeyStone_common_CPU_init(); + + +#endif diff --git a/bsp/ti-c6678/driver/drv_timer.c b/bsp/ti-c6678/driver/drv_timer.c new file mode 100644 index 0000000000..4cda450e49 --- /dev/null +++ b/bsp/ti-c6678/driver/drv_timer.c @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2021, Shenzhen Academy of Aerospace Technology + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2021-11-16 Dystopia the first version + */ + +#include "drv_timer.h" +#include "KeyStone_common.h" + +#include +#include + +/** + * @b Description + * @n + * The function initial system timer. + * Use local timer (==DNUM of a core) to generate a clock on TIMO0,interrupts are generated as well + * + * @param[] + * + * @retval + * NULL + */ +void hw_system_timer_init(void) +{ + // initial system timer interrupt + // map local timer interrupt to INT14 + gpCGEM_regs->INTMUX3 = (CSL_GEM_TINTLN<TOUTSEL = (DNUM*2)< + +#ifdef _BIG_ENDIAN +#define REG_PAIR(odd, even) unsigned long odd; unsigned long even +#else +#define REG_PAIR(odd, even) unsigned long even; unsigned long odd +#endif + +/* + * this struct defines the way the registers are stored on the + * stack during a system call. fields defined with REG_PAIR + * are saved and restored using double-word memory operations + * which means the word ordering of the pair depends on endianess. + */ + +struct rt_hw_register +{ + REG_PAIR(b17, b16); + REG_PAIR(b19, b18); + REG_PAIR(b21, b20); + REG_PAIR(b23, b22); + REG_PAIR(b25, b24); + REG_PAIR(b27, b26); + REG_PAIR(b29, b28); + REG_PAIR(b31, b30); + + REG_PAIR(b1, b0); + REG_PAIR(b3, b2); + REG_PAIR(b5, b4); + REG_PAIR(b7, b6); + REG_PAIR(b9, b8); + REG_PAIR(b11, b10); + REG_PAIR(b13, b12); + + REG_PAIR(a17, a16); + REG_PAIR(a19, a18); + REG_PAIR(a21, a20); + REG_PAIR(a23, a22); + REG_PAIR(a25, a24); + REG_PAIR(a27, a26); + REG_PAIR(a29, a28); + REG_PAIR(a31, a30); + + REG_PAIR(a1, a0); + REG_PAIR(a3, a2); + REG_PAIR(a5, a4); + REG_PAIR(a7, a6); + REG_PAIR(a9, a8); + REG_PAIR(a11, a10); + REG_PAIR(a13, a12); + + REG_PAIR(a15, a14); + REG_PAIR(sp, dp); +}; + +struct rt_hw_exp_stack_register +{ + REG_PAIR(tsr, orig_a4); + REG_PAIR(rilc, ilc); + REG_PAIR(pc, csr); + struct rt_hw_register hw_register; +}; + +extern cregister volatile unsigned int IERR; /* Internal Exception Report Register */ +extern cregister volatile unsigned int ECR; /* Exception Clear Register */ +extern cregister volatile unsigned int EFR; /* Exception Flag Register */ +extern cregister volatile unsigned int TSR; /* Task State Register */ +extern cregister volatile unsigned int ITSR; /* Interrupt Task State Register */ +extern cregister volatile unsigned int NTSR; /* NMI/exception Task State Register */ +extern cregister volatile unsigned int TSCL; /* Time Stamp Counter Register - Low Half */ +extern cregister volatile unsigned int TSCH; /* Time Stamp Counter Register - High Half */ +extern cregister volatile unsigned int DNUM; /* Core number */ + +#define get_creg(reg) reg +#define set_creg(reg, v) reg = (v) +#define or_creg(reg, n) reg |= (n) +#define and_creg(reg, n) reg &= (n) + +#define __dint() asm(" DINT") +#define __rint() asm(" RINT") + +#define __system_call() asm(" SWE") +#define __enter_idle() asm(" IDLE") +#define __nop() asm(" NOP") +#define __mfence() asm(" MFENCE") + +#define __SYSREG(ADDR, TYPE) (*(volatile TYPE*)(ADDR)) +#define __SYSREGA(ADDR, TYPE) ((volatile TYPE*)(ADDR)) + +extern void rt_hw_enable_exception(void); + +#endif /* __C66XX_H__ */ + diff --git a/libcpu/ti-dsp/c6x/context.asm b/libcpu/ti-dsp/c6x/context.asm new file mode 100644 index 0000000000..07affb6a1a --- /dev/null +++ b/libcpu/ti-dsp/c6x/context.asm @@ -0,0 +1,312 @@ +; +; Copyright (c) 2021, Shenzhen Academy of Aerospace Technology +; +; SPDX-License-Identifier: Apache-2.0 +; +; Change Logs: +; Date Author Notes +; 2021-11-16 Dystopia the first version +; + +;----------------------------------------------------------- +; context switch for C6678 DSP +;----------------------------------------------------------- + +;----------------------------------------------------------- +; macro definition +;----------------------------------------------------------- +DP .set B14 +SP .set B15 + +; +;----------------------------------------------------------- +; + +;----------------------------------------------------------- +; global variable +;----------------------------------------------------------- + .global rt_interrupt_from_thread + .global rt_interrupt_to_thread + .global rt_thread_switch_interrupt_flag + +; +;----------------------------------------------------------- +; + .sect ".text" +;----------------------------------------------------------- +; void rt_hw_enable_exception(void) +;----------------------------------------------------------- + .global rt_hw_enable_exception +rt_hw_enable_exception: + DINT + MVC .S2 TSR,B0 + MVC .S2 B3,NRP + MVK .L2 0xc,B1 + OR .D2 B0,B1,B0 + MVC .S2 B0,TSR ; Set GEE and XEN in TSR + B .S2 NRP + NOP 5 + +;----------------------------------------------------------- +; rt_base_t rt_hw_interrupt_enable(void) +;----------------------------------------------------------- + .global rt_hw_interrupt_disable +rt_hw_interrupt_disable: +;{ + MVC CSR,B4 + MV B4,A4 + AND 1,B4,B0 + [!B0] CLR B4,1,1,B4 + [B0] SET B4,1,1,B4 + CLR B4,0,0,B4 + MVC B4,CSR + B B3 + NOP 5 +;} + +;----------------------------------------------------------- +; void rt_hw_interrupt_enable(rt_base_t scr) +;----------------------------------------------------------- + .global rt_hw_interrupt_enable +rt_hw_interrupt_enable: +;{ + MVC A4,CSR + B B3 + NOP 5 +;} + +; +;----------------------------------------------------------- +; + +; +; void rt_hw_context_switch(rt_uint32 from, rt_uint32 to); +; A4 --> from +; B4 --> to +; + .global rt_hw_context_switch +rt_hw_context_switch: +; { + SUBAW .D2 SP,2,SP + ADD .D1X SP,-8,A15 + || STDW .D2T1 A15:A14,*SP--[3] ; Store A15:A14 + + STDW .D2T2 B13:B12,*SP--[1] ; Store B13:B12 + || STDW .D1T1 A13:A12,*A15--[1] ; Store A13:A12 + || MV B3,B13 + STDW .D2T2 B11:B10,*SP--[1] ; Store B11:B10 + || STDW .D1T1 A11:A10,*A15--[1] ; Store A11:A10 + || MVC .S2 CSR,B12 + STDW .D2T2 B13:B12,*SP--[1] ; Store PC:CSR + || MVC .S2 TSR,B5 + + MVC ILC,B11 ; + MVC RILC,B10 ; + STDW .D2T2 B11:B10,*SP--[1] ; Store RILC:ILC + || MV .S1X B5,A3 + + ZERO A2 ; + STDW .D2T1 A3:A2,*SP--[1] ; Store TSR:stack type + STW SP,*A4 ; Save thread's stack pointer + + MV B4,A4 ; + B rt_hw_context_switch_to + NOP 5 +;} + +; +; void rt_hw_context_switch_to(rt_uint32 to); +; A4 --> to +; + .global rt_hw_context_switch_to +rt_hw_context_switch_to: +;{ + LDW *A4,SP + NOP 4 + LDDW .D2T2 *++SP[1],B9:B8 ; get TSR (B9) and stack frame type (B8) + LDDW .D2T2 *++SP[1],B11:B10 ; get RILC (B11) and ILC (B10) + LDDW .D2T2 *++SP[1],B13:B12 ; get PC (B13) and CSR (B12) + NOP 2 + MV B8,B0 + [B0] B _rt_thread_interrupt_stack ; + NOP 5 +; +; this maybe do better +; + MVC .S2 B11,RILC ; Restore RILC + MVC .S2 B10,ILC ; Restore ILC + MV B13,B3 ; Restore PC + MVC .S2 B12,CSR ; Restore CSR + + LDDW *++SP[1],B11:B10 + LDDW *++SP[1],B13:B12 + LDDW *++SP[1],A11:A10 + LDDW *++SP[1],A13:A12 + LDDW *++SP[1],A15:A14 + B B3 ; Return to caller + ADDAW SP,2,SP + NOP 4 ; Delay slots +_rt_thread_interrupt_stack: + ADDAW .D1X SP,30,A15 + LDDW .D1T1 *++A15[1],A17:A16 + || LDDW .D2T2 *++SP[1],B17:B16 + LDDW .D1T1 *++A15[1],A19:A18 + || LDDW .D2T2 *++SP[1],B19:B18 + LDDW .D1T1 *++A15[1],A21:A20 + || LDDW .D2T2 *++SP[1],B21:B20 + LDDW .D1T1 *++A15[1],A23:A22 + || LDDW .D2T2 *++SP[1],B23:B22 + LDDW .D1T1 *++A15[1],A25:A24 + || LDDW .D2T2 *++SP[1],B25:B24 + LDDW .D1T1 *++A15[1],A27:A26 + || LDDW .D2T2 *++SP[1],B27:B26 + LDDW .D1T1 *++A15[1],A29:A28 + || LDDW .D2T2 *++SP[1],B29:B28 + LDDW .D1T1 *++A15[1],A31:A30 + || LDDW .D2T2 *++SP[1],B31:B30 + + LDDW .D1T1 *++A15[1],A1:A0 + || LDDW .D2T2 *++SP[1],B1:B0 + + LDDW .D1T1 *++A15[1],A3:A2 + || LDDW .D2T2 *++SP[1],B3:B2 + || MVC .S2 B9,ITSR ; Restore ITSR + LDDW .D1T1 *++A15[1],A5:A4 + || LDDW .D2T2 *++SP[1],B5:B4 + || MVC .S2 B11,RILC ; Restore RILC + LDDW .D1T1 *++A15[1],A7:A6 + || LDDW .D2T2 *++SP[1],B7:B6 + || MVC .S2 B10,ILC ; Restore ILC + + LDDW .D1T1 *++A15[1],A9:A8 + || LDDW .D2T2 *++SP[1],B9:B8 + || MVC .S2 B13,IRP ; Restore IPR + + LDDW .D1T1 *++A15[1],A11:A10 + || LDDW .D2T2 *++SP[1],B11:B10 + || MVC .S2 B12,CSR ; Restore CSR + + LDDW .D1T1 *++A15[1],A13:A12 + || LDDW .D2T2 *++SP[1],B13:B12 + + MV .D2X A15,SP + LDDW .D2T1 *++SP[1],A15:A14 + B IRP ; Return to point of interrupt + LDDW .D2T2 *+SP[1],SP:DP + NOP 4 ; Delay slots +;} + +; +;----------------------------------------------------------- +; + +; +; void rt_hw_context_switch_interrupt(rt_uint32_t from, rt_uint32_t to) +; A4 --> from +; B4 --> to + .global rt_hw_context_switch_interrupt +rt_hw_context_switch_interrupt: + SUB B15,0x8,B15 + STW B4,*B15[2] + STW A4,*B15[1] + LDW *+B14(rt_thread_switch_interrupt_flag),B4 + NOP 4 + CMPEQ 1,B4,B0 + [ B0] BNOP _reswitch,5 + MVK 1,B4 + STW B4,*+B14(rt_thread_switch_interrupt_flag) + MV A4,B4 + STW B4,*+B14(rt_interrupt_from_thread) +_reswitch: + LDW *B15[2],B4 + NOP 4 + STW B4,*+B14(rt_interrupt_to_thread) + ADD 8,B15,B15 + BNOP B3,5 +;} + +;----------------------------------------------------------- +; +;void rt_interrupt_context_restore(void) +; + .global rt_interrupt_context_restore +rt_interrupt_context_restore: +;{ +; if rt_switch_interrupt_flag set, jump to rt_hw_context_switch_interrupt and don't return + MVKL rt_thread_switch_interrupt_flag,A3 + MVKH rt_thread_switch_interrupt_flag,A3 + LDW *A3,A1 + NOP 4 + CMPEQ 1,A1,A2 + [A2] BNOP rt_preempt_context_restore,5 + NOP 5 + LDDW .D2T2 *++SP[1],B9:B8 ; get TSR (B9) + LDDW .D2T2 *++SP[1],B11:B10 ; get RILC (B11) and ILC (B10) + LDDW .D2T2 *++SP[1],B13:B12 ; get PC (B13) and CSR (B12) + + ADDAW .D1X SP,30,A15 + + LDDW .D1T1 *++A15[1],A17:A16 + || LDDW .D2T2 *++SP[1],B17:B16 + LDDW .D1T1 *++A15[1],A19:A18 + || LDDW .D2T2 *++SP[1],B19:B18 + LDDW .D1T1 *++A15[1],A21:A20 + || LDDW .D2T2 *++SP[1],B21:B20 + LDDW .D1T1 *++A15[1],A23:A22 + || LDDW .D2T2 *++SP[1],B23:B22 + LDDW .D1T1 *++A15[1],A25:A24 + || LDDW .D2T2 *++SP[1],B25:B24 + LDDW .D1T1 *++A15[1],A27:A26 + || LDDW .D2T2 *++SP[1],B27:B26 + LDDW .D1T1 *++A15[1],A29:A28 + || LDDW .D2T2 *++SP[1],B29:B28 + LDDW .D1T1 *++A15[1],A31:A30 + || LDDW .D2T2 *++SP[1],B31:B30 + + LDDW .D1T1 *++A15[1],A1:A0 + || LDDW .D2T2 *++SP[1],B1:B0 + LDDW .D1T1 *++A15[1],A3:A2 + || LDDW .D2T2 *++SP[1],B3:B2 + || MVC .S2 B9,ITSR + LDDW .D1T1 *++A15[1],A5:A4 + || LDDW .D2T2 *++SP[1],B5:B4 + || MVC .S2 B11,RILC + LDDW .D1T1 *++A15[1],A7:A6 + || LDDW .D2T2 *++SP[1],B7:B6 + || MVC .S2 B10,ILC + LDDW .D1T1 *++A15[1],A9:A8 + || LDDW .D2T2 *++SP[1],B9:B8 + || MVC .S2 B13,IRP + + LDDW .D1T1 *++A15[1],A11:A10 + || LDDW .D2T2 *++SP[1],B11:B10 + || MVC .S2 B12,CSR + LDDW .D1T1 *++A15[1],A13:A12 + || LDDW .D2T2 *++SP[1],B13:B12 + + MV .D2X A15,SP + LDDW .D2T1 *++SP[1],A15:A14 + B .S2 IRP ; return from interruption + LDDW .D2T2 *+SP[1],SP:DP + NOP 4 + +rt_preempt_context_restore: + ZERO A12 + STW A12,*A3 ; clear rt_thread_switch_interrupt_flag + + MVKL rt_interrupt_from_thread,A11 + MVKH rt_interrupt_from_thread,A11 + LDW *A11,A10 + NOP + MVKL rt_interrupt_to_thread,B10 + MVKH rt_interrupt_to_thread,B10 + LDW *B10,B11 + NOP 3 + STW SP,*A10 ; store sp in preempted tasks's TCB + MV B11,A4 ; + B rt_hw_context_switch_to + NOP 5 +;} + + .end + diff --git a/libcpu/ti-dsp/c6x/cpuport.c b/libcpu/ti-dsp/c6x/cpuport.c new file mode 100644 index 0000000000..a00a2e9046 --- /dev/null +++ b/libcpu/ti-dsp/c6x/cpuport.c @@ -0,0 +1,225 @@ +/* + * Copyright (c) 2021, Shenzhen Academy of Aerospace Technology + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2021-11-16 Dystopia the first version + */ + +#include +#include + +#include "trap.h" + +/*------------ rt_hw_cpu_shutdown() function ---------------------------------- + * DESCRIPTION: Shutdown CPU + * ARGUMENTS: + * None + * RETURNED VALUE: None +-----------------------------------------------------------------------------*/ +RT_WEAK void rt_hw_cpu_shutdown(void) +{ + rt_kprintf("shutdown...\n"); + + rt_hw_interrupt_disable(); + + RT_ASSERT(0); +} +//----------------------------------------------------------------------------- + +/*------------ nested_exception_handler() function --------------------------- + * DESCRIPTION: Function handles Nested Exception + * ARGUMENTS: + * None + * RETURNED VALUE: None +-----------------------------------------------------------------------------*/ + +void nested_exception_handler(void) +{ + for ( ; ; ); +} +//----------------------------------------------------------------------------- + + +/*------------ hw_nmi_handler() function -------------------------------------- + * DESCRIPTION: Function handles NMI interrupt + * ARGUMENTS: + * None + * RETURNED VALUE: None +-----------------------------------------------------------------------------*/ +void hw_nmi_handler(struct rt_hw_exp_stack_register *regs) +{ + for ( ; ; ); +} +//----------------------------------------------------------------------------- + + +/*------------ hw_bad_handler() function -------------------------------------- + * DESCRIPTION: Function handles Bad interrupt + * ARGUMENTS: + * None + * RETURNED VALUE: None +-----------------------------------------------------------------------------*/ +void hw_bad_handler(void) +{ + for ( ; ; ); +} +//----------------------------------------------------------------------------- + + +/*------------ hw_int4_handler() function ------------------------------------- + * DESCRIPTION: Function handles INT4 interrupt + * ARGUMENTS: + * None + * RETURNED VALUE: None +-----------------------------------------------------------------------------*/ +void hw_int4_handler(void) +{ + +} +//----------------------------------------------------------------------------- + + +/*------------ hw_int5_handler() function ------------------------------------- + * DESCRIPTION: Function handles INT5 interrupt + * ARGUMENTS: + * None + * RETURNED VALUE: None +-----------------------------------------------------------------------------*/ +void hw_int5_handler(void) +{ + +} +//----------------------------------------------------------------------------- + + +/*------------ hw_int6_handler() function ------------------------------------- + * DESCRIPTION: Function handles INT6 interrupt + * ARGUMENTS: + * None + * RETURNED VALUE: None +-----------------------------------------------------------------------------*/ +void hw_int6_handler(void) +{ + +} +//----------------------------------------------------------------------------- + + +/*------------ hw_int7_handler() function ------------------------------------- + * DESCRIPTION: Function handles INT7 interrupt + * ARGUMENTS: + * None + * RETURNED VALUE: None +-----------------------------------------------------------------------------*/ +void hw_int7_handler(void) +{ + +} +//----------------------------------------------------------------------------- + + +/*------------ hw_int8_handler() function ------------------------------------- + * DESCRIPTION: Function handles INT8 interrupt + * ARGUMENTS: + * None + * RETURNED VALUE: None +-----------------------------------------------------------------------------*/ +void hw_int8_handler(void) +{ + +} +//----------------------------------------------------------------------------- + + +/*------------ hw_int9_handler() function ------------------------------------- + * DESCRIPTION: Function handles INT9 interrupt + * ARGUMENTS: + * None + * RETURNED VALUE: None +-----------------------------------------------------------------------------*/ +void hw_int9_handler(void) +{ + +} +//----------------------------------------------------------------------------- + + +/*------------ hw_int10_handler() function ------------------------------------ + * DESCRIPTION: Function handles INT10 interrupt + * ARGUMENTS: + * None + * RETURNED VALUE: None +-----------------------------------------------------------------------------*/ +void hw_int10_handler(void) +{ + +} +//----------------------------------------------------------------------------- + + +/*------------ hw_int11_handler() function ------------------------------------ + * DESCRIPTION: Function handles INT11 interrupt + * ARGUMENTS: + * None + * RETURNED VALUE: None +-----------------------------------------------------------------------------*/ +void hw_int11_handler(void) +{ + +} +//----------------------------------------------------------------------------- + + +/*------------ hw_int12_handler() function ------------------------------------ + * DESCRIPTION: Function handles INT12 interrupt + * ARGUMENTS: + * None + * RETURNED VALUE: None +-----------------------------------------------------------------------------*/ +void hw_int12_handler(void) +{ +} +//----------------------------------------------------------------------------- + + +/*------------ hw_int13_handler() function ------------------------------------ + * DESCRIPTION: Function handles INT13 interrupt + * ARGUMENTS: + * None + * RETURNED VALUE: None +-----------------------------------------------------------------------------*/ +void hw_int13_handler(void) +{ + +} +//----------------------------------------------------------------------------- + + +/*------------------ hw_int14_handler() function ------------------------------ + * DESCRIPTION: Function handles INT14 interrupt + * ARGUMENTS: + * None + * RETURNED VALUE: +-----------------------------------------------------------------------------*/ +void hw_int14_handler(void) +{ +extern void rt_hw_systick_isr(); + rt_hw_systick_isr(); +} +//----------------------------------------------------------------------------- + + +/*------------ hw_int15_handler() function ------------------------------------ + * DESCRIPTION: Function handles INT15 interrupt + * ARGUMENTS: + * None + * RETURNED VALUE: None +-----------------------------------------------------------------------------*/ +void hw_int15_handler(void) +{ + +} + diff --git a/libcpu/ti-dsp/c6x/inct.asm b/libcpu/ti-dsp/c6x/inct.asm new file mode 100644 index 0000000000..4f866e4800 --- /dev/null +++ b/libcpu/ti-dsp/c6x/inct.asm @@ -0,0 +1,374 @@ +; +; Copyright (c) 2021, Shenzhen Academy of Aerospace Technology +; +; SPDX-License-Identifier: Apache-2.0 +; +; Change Logs: +; Date Author Notes +; 2021-11-16 Dystopia the first version +; + +;----------------------------------------------------------- +; interrupt handler for C6678 DSP +;----------------------------------------------------------- + +;----------------------------------------------------------- +; macro definition +;----------------------------------------------------------- +DP .set B14 +SP .set B15 +; +;----------------------------------------------------------- +; + +;----------------------------------------------------------- +; global function +;----------------------------------------------------------- + .global _nmi_handler + .global _bad_handler + .global _int4_handler + .global _int5_handler + .global _int6_handler + .global _int7_handler + .global _int8_handler + .global _int9_handler + .global _int10_handler + .global _int11_handler + .global _int12_handler + .global _int13_handler + .global _int14_handler + .global _int15_handler +; +;----------------------------------------------------------- +; + +;----------------------------------------------------------- +; extern function +;----------------------------------------------------------- + .ref hw_nmi_handler + .ref hw_bad_handler + .ref hw_int4_handler + .ref hw_int5_handler + .ref hw_int6_handler + .ref hw_int7_handler + .ref hw_int8_handler + .ref hw_int9_handler + .ref hw_int10_handler + .ref hw_int11_handler + .ref hw_int12_handler + .ref hw_int13_handler + .ref hw_int14_handler + .ref hw_int15_handler + .ref rt_hw_process_exception + .ref rt_interrupt_context_restore +; +;----------------------------------------------------------- +; + +; +;----------------------------------------------------------- +; + +;----------------------------------------------------------- +; macro definition +;----------------------------------------------------------- +SAVE_ALL .macro __rp, __tsr + STDW .D2T2 SP:DP,*--SP[1] + SUBAW .D2 SP,2,SP + ADD .D1X SP,-8,A15 + || STDW .D2T1 A15:A14,*SP--[16] ; save A15:A14 + + STDW .D2T2 B13:B12,*SP--[1] + || STDW .D1T1 A13:A12,*A15--[1] + || MVC .S2 __rp,B13 + + STDW .D2T2 B11:B10,*SP--[1] + || STDW .D1T1 A11:A10,*A15--[1] + || MVC .S2 CSR,B12 + + STDW .D2T2 B9:B8,*SP--[1] + || STDW .D1T1 A9:A8,*A15--[1] + || MVC .S2 RILC,B11 + STDW .D2T2 B7:B6,*SP--[1] + || STDW .D1T1 A7:A6,*A15--[1] + || MVC .S2 ILC,B10 + + STDW .D2T2 B5:B4,*SP--[1] + || STDW .D1T1 A5:A4,*A15--[1] + + STDW .D2T2 B3:B2,*SP--[1] + || STDW .D1T1 A3:A2,*A15--[1] + || MVC .S2 __tsr,B5 + + STDW .D2T2 B1:B0,*SP--[1] + || STDW .D1T1 A1:A0,*A15--[1] + || MV .S1X B5,A5 + + STDW .D2T2 B31:B30,*SP--[1] + || STDW .D1T1 A31:A30,*A15--[1] + || MVKL 1,A4 + + STDW .D2T2 B29:B28,*SP--[1] + || STDW .D1T1 A29:A28,*A15--[1] + STDW .D2T2 B27:B26,*SP--[1] + || STDW .D1T1 A27:A26,*A15--[1] + STDW .D2T2 B25:B24,*SP--[1] + || STDW .D1T1 A25:A24,*A15--[1] + STDW .D2T2 B23:B22,*SP--[1] + || STDW .D1T1 A23:A22,*A15--[1] + STDW .D2T2 B21:B20,*SP--[1] + || STDW .D1T1 A21:A20,*A15--[1] + STDW .D2T2 B19:B18,*SP--[1] + || STDW .D1T1 A19:A18,*A15--[1] + STDW .D2T2 B17:B16,*SP--[1] + || STDW .D1T1 A17:A16,*A15--[1] + + STDW .D2T2 B13:B12,*SP--[1] ; save PC and CSR + + STDW .D2T2 B11:B10,*SP--[1] ; save RILC and ILC + STDW .D2T1 A5:A4,*SP--[1] ; save TSR and orig A4 + .endm + +RESTORE_ALL .macro __rp, __tsr + LDDW .D2T2 *++SP[1],B9:B8 ; get TSR (B9) + LDDW .D2T2 *++SP[1],B11:B10 ; get RILC (B11) and ILC (B10) + LDDW .D2T2 *++SP[1],B13:B12 ; get PC (B13) and CSR (B12) + + ADDAW .D1X SP,30,A15 + + LDDW .D1T1 *++A15[1],A17:A16 + || LDDW .D2T2 *++SP[1],B17:B16 + LDDW .D1T1 *++A15[1],A19:A18 + || LDDW .D2T2 *++SP[1],B19:B18 + LDDW .D1T1 *++A15[1],A21:A20 + || LDDW .D2T2 *++SP[1],B21:B20 + LDDW .D1T1 *++A15[1],A23:A22 + || LDDW .D2T2 *++SP[1],B23:B22 + LDDW .D1T1 *++A15[1],A25:A24 + || LDDW .D2T2 *++SP[1],B25:B24 + LDDW .D1T1 *++A15[1],A27:A26 + || LDDW .D2T2 *++SP[1],B27:B26 + LDDW .D1T1 *++A15[1],A29:A28 + || LDDW .D2T2 *++SP[1],B29:B28 + LDDW .D1T1 *++A15[1],A31:A30 + || LDDW .D2T2 *++SP[1],B31:B30 + + LDDW .D1T1 *++A15[1],A1:A0 + || LDDW .D2T2 *++SP[1],B1:B0 + LDDW .D1T1 *++A15[1],A3:A2 + || LDDW .D2T2 *++SP[1],B3:B2 + || MVC .S2 B9,__tsr + LDDW .D1T1 *++A15[1],A5:A4 + || LDDW .D2T2 *++SP[1],B5:B4 + || MVC .S2 B11,RILC + LDDW .D1T1 *++A15[1],A7:A6 + || LDDW .D2T2 *++SP[1],B7:B6 + || MVC .S2 B10,ILC + LDDW .D1T1 *++A15[1],A9:A8 + || LDDW .D2T2 *++SP[1],B9:B8 + || MVC .S2 B13,__rp + + LDDW .D1T1 *++A15[1],A11:A10 + || LDDW .D2T2 *++SP[1],B11:B10 + || MVC .S2 B12,CSR + LDDW .D1T1 *++A15[1],A13:A12 + || LDDW .D2T2 *++SP[1],B13:B12 + + MV .D2X A15,SP + LDDW .D2T1 *++SP[1],A15:A14 + B .S2 __rp ; return from interruption + LDDW .D2T2 *+SP[1],SP:DP + NOP 4 + .endm +;----------------------------------------------------------- +; interrupt macro definition +;----------------------------------------------------------- +RT_INTERRUPT_ENTRY .macro + SAVE_ALL IRP,ITSR + .endm + +RT_CALL_INT .macro __isr + CALLP __isr,B3 + B .S1 rt_interrupt_context_restore + NOP 5 + .endm +;----------------------------------------------------------- +; execption macro definition +;----------------------------------------------------------- +RT_EXECPTION_ENTRY .macro + SAVE_ALL NRP,NTSR + .endm + +RT_EXECPTION_EXIT .macro + RESTORE_ALL NRP,NTSR + .endm + +; +;----------------------------------------------------------- +; + + .sect ".text" +; +;----------------------------------------------------------- +; + +;----------------------------------------------------------- +; handler NMI interrupt +;----------------------------------------------------------- +_nmi_handler: +;{ + RT_EXECPTION_ENTRY + MVC .S2 EFR,B2 + CMPEQ .L2 1,B2,B2 + || MVC .S2 TSR,B1 + MV .D1X B2,A2 + || CLR .S2 B1,10,10,B1 + MVC .S2 B1,TSR + [!A2] MVKL .S1 rt_hw_process_exception,A0 + ||[B2] MVKL .S2 rt_hw_software_exception,B1 + [!A2] MVKH .S1 rt_hw_process_exception,A0 + ||[B2] MVKH .S2 rt_hw_software_exception,B1 + [!B2] B .S2X A0 + [B2] B .S2 B1 + [!B2] ADDAW .D2 SP,2,B1 + [!B2] MV .D1X B1,A4 + ADDKPC .S2 ret_from_trap,B3,2 +; +; return from trap +; +ret_from_trap: + MV .D2X A4,B0 + [!B0] MVKL .S2 ret_from_exception,B3 + [!B0] MVKH .S2 ret_from_exception,B3 + [!B0] BNOP .S2 B3,5 +; +; return from traprestore exception context +; +ret_from_exception: + RT_EXECPTION_EXIT +; +rt_hw_software_exception: + MVKL .S1 rt_hw_process_exception,A0 + MVKH .S1 rt_hw_process_exception,A0 + B .S2X A0 + ADDAW .D2 SP,2,B1 + MV .D1X B1,A4 + ADDKPC .S2 ret_from_trap,B3,2 + NOP 2 +;} + +;----------------------------------------------------------- +; handler bad interrupt +;----------------------------------------------------------- +_bad_handler: +;{ + RT_INTERRUPT_ENTRY + RT_CALL_INT hw_bad_handler +;} + +;----------------------------------------------------------- +; handler INT4 interrupt +;----------------------------------------------------------- +_int4_handler: +;{ + RT_INTERRUPT_ENTRY + RT_CALL_INT hw_int4_handler +;} + +;----------------------------------------------------------- +; handler INT5 interrupt +;----------------------------------------------------------- +_int5_handler: +;{ + RT_INTERRUPT_ENTRY + RT_CALL_INT hw_int5_handler +;} + +;----------------------------------------------------------- +; handler INT6 interrupt +;----------------------------------------------------------- +_int6_handler: +;{ + RT_INTERRUPT_ENTRY + RT_CALL_INT hw_int6_handler +;} + +;----------------------------------------------------------- +; handler INT7 interrupt +;----------------------------------------------------------- +_int7_handler: +;{ + RT_INTERRUPT_ENTRY + RT_CALL_INT hw_int7_handler +;} +;----------------------------------------------------------- +; handler INT8 interrupt +;----------------------------------------------------------- +_int8_handler: +;{ + RT_INTERRUPT_ENTRY + RT_CALL_INT hw_int8_handler +;} + +;----------------------------------------------------------- +; handler INT9 interrupt +;----------------------------------------------------------- +_int9_handler: +;{ + RT_INTERRUPT_ENTRY + RT_CALL_INT hw_int9_handler +;} + +;----------------------------------------------------------- +; handler INT10 interrupt +;----------------------------------------------------------- +_int10_handler: +;{ + RT_INTERRUPT_ENTRY + RT_CALL_INT hw_int10_handler +;} + +;----------------------------------------------------------- +; handler INT11 interrupt +;----------------------------------------------------------- +_int11_handler: +;{ + RT_INTERRUPT_ENTRY + RT_CALL_INT hw_int11_handler +;} + +;----------------------------------------------------------- +; handler INT12 interrupt +;----------------------------------------------------------- +_int12_handler: +;{ + RT_INTERRUPT_ENTRY + RT_CALL_INT hw_int12_handler +;} + +;----------------------------------------------------------- +; handler INT13 interrupt +;----------------------------------------------------------- +_int13_handler: +;{ + RT_INTERRUPT_ENTRY + RT_CALL_INT hw_int13_handler +;} + +;----------------------------------------------------------- +; handler INT14 interrupt +;----------------------------------------------------------- +_int14_handler: +;{ + RT_INTERRUPT_ENTRY + RT_CALL_INT hw_int14_handler +;} +;----------------------------------------------------------- +; handler INT15 interrupt +;----------------------------------------------------------- +_int15_handler: +;{ + RT_INTERRUPT_ENTRY + RT_CALL_INT hw_int15_handler +;} + .end diff --git a/libcpu/ti-dsp/c6x/interrupt.c b/libcpu/ti-dsp/c6x/interrupt.c new file mode 100644 index 0000000000..69205e0d38 --- /dev/null +++ b/libcpu/ti-dsp/c6x/interrupt.c @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2021, Shenzhen Academy of Aerospace Technology + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2021-11-16 Dystopia the first version + */ + + +#include "c66xx.h" +#include "interrupt.h" + +#define MAX_HANDLERS 128 + +extern volatile rt_uint8_t rt_interrupt_nest; +struct rt_irq_desc isr_table[MAX_HANDLERS]; +rt_uint32_t rt_interrupt_from_thread; +rt_uint32_t rt_interrupt_to_thread; +rt_uint32_t rt_thread_switch_interrupt_flag; + +/** + * This function will initialize hardware interrupt + */ +void rt_hw_interrupt_init(void) +{ + /* init exceptions table */ + rt_memset(isr_table, 0x00, sizeof(isr_table)); + + /* init interrupt nest, and context in thread sp */ + rt_interrupt_nest = 0; + rt_interrupt_from_thread = 0; + rt_interrupt_to_thread = 0; + rt_thread_switch_interrupt_flag = 0; +} + +/** + * This function will mask a interrupt. + * @param vector the interrupt number + */ +void rt_hw_interrupt_mask(int vector) +{ + if (vector < 0 || vector >= MAX_HANDLERS) + return; +} + +/** + * This function will un-mask a interrupt. + * @param vector the interrupt number + */ +void rt_hw_interrupt_umask(int vector) +{ + if (vector < 0 || vector >= MAX_HANDLERS) + return; +} + +/** + * This function will install a interrupt service routine to a interrupt. + * @param vector the interrupt number + * @param new_handler the interrupt service routine to be installed + * @param old_handler the old interrupt service routine + */ +rt_isr_handler_t rt_hw_interrupt_install(int vector, rt_isr_handler_t handler, + void *param, const char *name) +{ + rt_isr_handler_t old_handler = RT_NULL; + + if (vector < MAX_HANDLERS || vector >= 0) + { + old_handler = isr_table[vector].handler; + + if (handler != RT_NULL) + { +#ifdef RT_USING_INTERRUPT_INFO + rt_strncpy(isr_table[vector].name, name, RT_NAME_MAX); +#endif /* RT_USING_INTERRUPT_INFO */ + isr_table[vector].handler = handler; + isr_table[vector].param = param; + } + } + + return old_handler; +} + +void rt_hw_interrupt_clear(int vector) +{ + if (vector < 0 || vector >= MAX_HANDLERS) + return; +} diff --git a/libcpu/ti-dsp/c6x/interrupt.h b/libcpu/ti-dsp/c6x/interrupt.h new file mode 100644 index 0000000000..de7935b38a --- /dev/null +++ b/libcpu/ti-dsp/c6x/interrupt.h @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2021, Shenzhen Academy of Aerospace Technology + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2021-11-16 Dystopia the first version + */ + +#ifndef __INTERRUPT_H__ +#define __INTERRUPT_H__ + +#include +#include + +void rt_hw_interrupt_init(void); +void rt_hw_interrupt_mask(int vector); +void rt_hw_interrupt_umask(int vector); +void rt_hw_interrupt_clear(int vector); +rt_isr_handler_t rt_hw_interrupt_install(int vector, rt_isr_handler_t handler, + void *param, const char *name); + +#endif /* __INTERRUPT_H__ */ diff --git a/libcpu/ti-dsp/c6x/stack.asm b/libcpu/ti-dsp/c6x/stack.asm new file mode 100644 index 0000000000..4415a9767c --- /dev/null +++ b/libcpu/ti-dsp/c6x/stack.asm @@ -0,0 +1,103 @@ +; +; Copyright (c) 2021, Shenzhen Academy of Aerospace Technology +; +; SPDX-License-Identifier: Apache-2.0 +; +; Change Logs: +; Date Author Notes +; 2021-11-16 Dystopia the first version +; + +;----------------------------------------------------------- +; build system stack for C6678 DSP +;----------------------------------------------------------- + +;----------------------------------------------------------- +; macro definition +;----------------------------------------------------------- +ADDRESS_MSK .set 0xFFFFFFF0 + +; +;----------------------------------------------------------- +; + + .sect ".text" +; +; rt_uint8_t *rt_hw_stack_init(void *tentry, void *parameter, rt_uint8_t *stack_addr, void *texit) +; tentry --> A4 +; parameter --> B4 +; stack_addr --> A6 +; texit --> B6 +;{ + .global rt_hw_stack_init +rt_hw_stack_init: + SUB A6,1,B1 ; + MVKL ADDRESS_MSK,A1 ; + MVKH ADDRESS_MSK,A1 ; Build address mask + MVC CSR,B0 ; + AND -2,B0,B0 ; Clear GIE bit + OR 2,B0,B0 ; Set PGIE bit for interrupt return + AND A1,B1,B1 ; Ensure alignment +; +; Actually build the stack frame. +; + MV B1,A3 + MV B14,A2 + STDW A3:A2,*--B1[1] ; Initial B15:B14 + SUBAW .D2 B1,2,B1 + ZERO A2 + ZERO A3 ; Clear value + STDW A3:A2,*B1--[1] ; Initial A15:A14 + STDW A3:A2,*B1--[1] ; Initial A13:A12 + STDW A3:A2,*B1--[1] ; Initial A11:A10 + STDW A3:A2,*B1--[1] ; Initial A9:A8 + STDW A3:A2,*B1--[1] ; Initial A7:A6 + MV B4,A2 + STDW A3:A2,*B1--[1] ; Initial A5:A4 + ZERO A2 + STDW A3:A2,*B1--[1] ; Initial A3:A2 + STDW A3:A2,*B1--[1] ; Initial A1:A0 + + STDW A3:A2,*B1--[1] ; Initial A31:A30 + STDW A3:A2,*B1--[1] ; Initial A29:A28 + STDW A3:A2,*B1--[1] ; Initial A27:A26 + STDW A3:A2,*B1--[1] ; Initial A25:A24 + STDW A3:A2,*B1--[1] ; Initial A23:A22 + STDW A3:A2,*B1--[1] ; Initial A21:A20 + STDW A3:A2,*B1--[1] ; Initial A19:A18 + STDW A3:A2,*B1--[1] ; Initial A17:A16 + + STDW A3:A2,*B1--[1] ; Initial B13:B12 + STDW A3:A2,*B1--[1] ; Initial B11:B10 + STDW A3:A2,*B1--[1] ; Initial B9:B8 + STDW A3:A2,*B1--[1] ; Initial B7:B6 + STDW A3:A2,*B1--[1] ; Initial B5:B4 + MV B6,A3 + STDW A3:A2,*B1--[1] ; Initial B3:B2 + ZERO A3 + STDW A3:A2,*B1--[1] ; Initial B1:B0 + + STDW A3:A2,*B1--[1] ; Initial B31:B30 + STDW A3:A2,*B1--[1] ; Initial B29:B28 + STDW A3:A2,*B1--[1] ; Initial B27:B26 + STDW A3:A2,*B1--[1] ; Initial B25:B24 + STDW A3:A2,*B1--[1] ; Initial B23:B22 + STDW A3:A2,*B1--[1] ; Initial B21:B20 + STDW A3:A2,*B1--[1] ; Initial B19:B18 + STDW A3:A2,*B1--[1] ; Initial B17:B16 + + MV A4,A3 + MV B0,A2 + STDW A3:A2,*B1--[1] ; Initial PC:CSR + + ZERO A2 + ZERO A3 + STDW A3:A2,*B1--[1] ; Initial ILC:RILC + B B3 + MVKL 0x3,B0 + MV B0,A3 + MVKL 1,A2 + STDW A3:A2,*B1--[1] ; Initial TSR:stack type + MV B1,A4 ; Save to TCB +;} + .end diff --git a/libcpu/ti-dsp/c6x/trap.c b/libcpu/ti-dsp/c6x/trap.c new file mode 100644 index 0000000000..eb1863fa9c --- /dev/null +++ b/libcpu/ti-dsp/c6x/trap.c @@ -0,0 +1,352 @@ +/* + * Copyright (c) 2021, Shenzhen Academy of Aerospace Technology + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2021-11-16 Dystopia the first version + */ + +#include "trap.h" +#include "c66xx.h" + +#include +#include + +void rt_trap_init(void) +{ + ack_exception(EXCEPT_TYPE_NXF); + ack_exception(EXCEPT_TYPE_EXC); + ack_exception(EXCEPT_TYPE_IXF); + ack_exception(EXCEPT_TYPE_SXF); + rt_hw_enable_exception(); +} + +void show_regs(struct rt_hw_exp_stack_register *regs) +{ + rt_kprintf("\n"); + rt_kprintf("PC: %08lx SP: %08lx\n", + regs->pc, regs->hw_register.sp); + rt_kprintf("Status: %08lx ORIG_A4: %08lx\n", + regs->csr, regs->orig_a4); + rt_kprintf("A0: %08lx B0: %08lx\n", + regs->hw_register.a0, regs->hw_register.b0); + rt_kprintf("A1: %08lx B1: %08lx\n", + regs->hw_register.a1, regs->hw_register.b1); + rt_kprintf("A2: %08lx B2: %08lx\n", + regs->hw_register.a2, regs->hw_register.b2); + rt_kprintf("A3: %08lx B3: %08lx\n", + regs->hw_register.a3, regs->hw_register.b3); + rt_kprintf("A4: %08lx B4: %08lx\n", + regs->hw_register.a4, regs->hw_register.b4); + rt_kprintf("A5: %08lx B5: %08lx\n", + regs->hw_register.a5, regs->hw_register.b5); + rt_kprintf("A6: %08lx B6: %08lx\n", + regs->hw_register.a6, regs->hw_register.b6); + rt_kprintf("A7: %08lx B7: %08lx\n", + regs->hw_register.a7, regs->hw_register.b7); + rt_kprintf("A8: %08lx B8: %08lx\n", + regs->hw_register.a8, regs->hw_register.b8); + rt_kprintf("A9: %08lx B9: %08lx\n", + regs->hw_register.a9, regs->hw_register.b9); + rt_kprintf("A10: %08lx B10: %08lx\n", + regs->hw_register.a10, regs->hw_register.b10); + rt_kprintf("A11: %08lx B11: %08lx\n", + regs->hw_register.a11, regs->hw_register.b11); + rt_kprintf("A12: %08lx B12: %08lx\n", + regs->hw_register.a12, regs->hw_register.b12); + rt_kprintf("A13: %08lx B13: %08lx\n", + regs->hw_register.a13, regs->hw_register.b13); + rt_kprintf("A14: %08lx B14: %08lx\n", + regs->hw_register.a14, regs->hw_register.dp); + rt_kprintf("A15: %08lx B15: %08lx\n", + regs->hw_register.a15, regs->hw_register.sp); + rt_kprintf("A16: %08lx B16: %08lx\n", + regs->hw_register.a16, regs->hw_register.b16); + rt_kprintf("A17: %08lx B17: %08lx\n", + regs->hw_register.a17, regs->hw_register.b17); + rt_kprintf("A18: %08lx B18: %08lx\n", + regs->hw_register.a18, regs->hw_register.b18); + rt_kprintf("A19: %08lx B19: %08lx\n", + regs->hw_register.a19, regs->hw_register.b19); + rt_kprintf("A20: %08lx B20: %08lx\n", + regs->hw_register.a20, regs->hw_register.b20); + rt_kprintf("A21: %08lx B21: %08lx\n", + regs->hw_register.a21, regs->hw_register.b21); + rt_kprintf("A22: %08lx B22: %08lx\n", + regs->hw_register.a22, regs->hw_register.b22); + rt_kprintf("A23: %08lx B23: %08lx\n", + regs->hw_register.a23, regs->hw_register.b23); + rt_kprintf("A24: %08lx B24: %08lx\n", + regs->hw_register.a24, regs->hw_register.b24); + rt_kprintf("A25: %08lx B25: %08lx\n", + regs->hw_register.a25, regs->hw_register.b25); + rt_kprintf("A26: %08lx B26: %08lx\n", + regs->hw_register.a26, regs->hw_register.b26); + rt_kprintf("A27: %08lx B27: %08lx\n", + regs->hw_register.a27, regs->hw_register.b27); + rt_kprintf("A28: %08lx B28: %08lx\n", + regs->hw_register.a28, regs->hw_register.b28); + rt_kprintf("A29: %08lx B29: %08lx\n", + regs->hw_register.a29, regs->hw_register.b29); + rt_kprintf("A30: %08lx B30: %08lx\n", + regs->hw_register.a30, regs->hw_register.b30); + rt_kprintf("A31: %08lx B31: %08lx\n", + regs->hw_register.a31, regs->hw_register.b31); +} + + +void do_trap(struct rt_exception_info *except_info, struct rt_hw_exp_stack_register *regs) +{ + rt_kprintf("Enter exception: %s\n", except_info->kernel_str); + + show_regs(regs); + + for( ; ; ); +} + + +static struct rt_exception_info iexcept_table[10] = { + { " - instruction fetch", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - fetch packet", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - execute packet", ABORT_TYPE_UNDDEF, ABORT_OPCODE_ILL }, + { " - undefined instruction", ABORT_TYPE_UNDDEF, ABORT_OPCODE_ILL }, + { " - resource conflict", ABORT_TYPE_UNDDEF, ABORT_OPCODE_ILL }, + { " - resource access", ABORT_TYPE_UNDDEF, ABORT_PRVREG_ILL }, + { " - privilege", ABORT_TYPE_UNDDEF, ABORT_PRVOPC_ILL }, + { " - loops buffer", ABORT_TYPE_UNDDEF, ABORT_PRVOPC_ILL }, + { " - software exception", ABORT_TYPE_UNDDEF, ABORT_ILLTRP_ILL }, + { " - unknown exception", ABORT_TYPE_UNDDEF, ABORT_PRVOPC_ILL } +}; + +/* + * Process an internal exception (non maskable) + */ +static int process_iexcept(struct rt_hw_exp_stack_register *regs) +{ + unsigned int iexcept_report = get_iexcept(); + unsigned int iexcept_num; + + ack_exception(EXCEPT_TYPE_IXF); + + while(iexcept_report) { + iexcept_num = __ffs(iexcept_report); + iexcept_report &= ~(1 << iexcept_num); + set_iexcept(iexcept_report); + + if (*(unsigned int *)regs->pc == BKPT_OPCODE) { + /* This is a breakpoint */ + struct rt_exception_info bkpt_exception = { " - undefined instruction", ABORT_TYPE_UNDDEF, ABORT_BRKPT_ILL }; + do_trap(&bkpt_exception, regs); + iexcept_report &= ~(0xFF); + set_iexcept(iexcept_report); + continue; + } + + do_trap(&iexcept_table[iexcept_num], regs); + } + return 0; +} + +static struct rt_exception_info except_table[128] = { + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + + { " - CPU memory protection fault", ABORT_TYPE_MAP, ABORT_BUS_ACCERR }, + { " - CPU memory protection fault in L1P", ABORT_TYPE_MAP, ABORT_BUS_ACCERR }, + { " - DMA memory protection fault in L1P", ABORT_TYPE_MAP, ABORT_BUS_ACCERR }, + { " - CPU memory protection fault in L1D", ABORT_TYPE_MAP, ABORT_BUS_ACCERR }, + { " - DMA memory protection fault in L1D", ABORT_TYPE_MAP, ABORT_BUS_ACCERR }, + { " - CPU memory protection fault in L2", ABORT_TYPE_MAP, ABORT_BUS_ACCERR }, + { " - DMA memory protection fault in L2", ABORT_TYPE_MAP, ABORT_BUS_ACCERR }, + { " - EMC CPU memory protection fault", ABORT_TYPE_MAP, ABORT_BUS_ACCERR }, + { " - EMC bus error", ABORT_TYPE_MAP, ABORT_BUS_ADDRERR } +}; + +/* + * Process an external exception (maskable) + */ +static void process_except(struct rt_hw_exp_stack_register *regs) +{ + int except_num; + int bank = 0; + int i; + + for (i = 0; i <= 3; i++) { + while (INTC_MEXPMASK[i]) { + __dint(); + except_num = __ffs(INTC_MEXPMASK[i]); + INTC_MEXPMASK[i] &= ~(1 << except_num); /* ack the external exception */ + __rint(); + do_trap(&except_table[except_num + (bank << 5)], regs); + } + bank++; + } + + ack_exception(EXCEPT_TYPE_EXC); +} + +extern void hw_nmi_handler(struct rt_hw_exp_stack_register *regs); + +/* + * Main exception processing + */ +int rt_hw_process_exception(struct rt_hw_exp_stack_register *regs) +{ + int type; + int type_num; + int ie_num = 9; /* default is unknown exception */ + + while ((type = get_except_type()) != 0) { + type_num = fls(type) - 1; + + switch(type_num) { + case EXCEPT_TYPE_NXF: /* NMI exception */ + ack_exception(EXCEPT_TYPE_NXF); /* clear exception */ + if (hw_nmi_handler != RT_NULL) + hw_nmi_handler(regs); + break; + + case EXCEPT_TYPE_IXF: /* internal exception */ + if (process_iexcept(regs)) + return 1; + break; + + case EXCEPT_TYPE_EXC: /* external exception */ + process_except(regs); + break; + + case EXCEPT_TYPE_SXF: /* software exception */ + ie_num = 8; + ack_exception(type_num); + break; + default: /* clear exception */ + ack_exception(type_num); + do_trap(&iexcept_table[ie_num], regs); + break; + } + } + return 0; +} + diff --git a/libcpu/ti-dsp/c6x/trap.h b/libcpu/ti-dsp/c6x/trap.h new file mode 100644 index 0000000000..5494fa900b --- /dev/null +++ b/libcpu/ti-dsp/c6x/trap.h @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2021, Shenzhen Academy of Aerospace Technology + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2021-11-16 Dystopia the first version + */ + +#ifndef __TRAP_H__ +#define __TRAP_H__ + +#include "c66xx.h" + +/* + * exception operation macro + */ +#define disable_exception() +#define get_except_type() EFR +#define ack_exception(type) ECR = 1ul << (type) +#define get_iexcept() IERR +#define set_iexcept(mask) IERR = (mask) + +/* + * exception types + */ +#define EXCEPT_TYPE_NXF 31 /* NMI */ +#define EXCEPT_TYPE_EXC 30 /* external exception */ +#define EXCEPT_TYPE_IXF 1 /* internal exception */ +#define EXCEPT_TYPE_SXF 0 /* software exception */ + +#define EXCEPT_CAUSE_LBX (1 << 7) /* loop buffer exception */ +#define EXCEPT_CAUSE_PRX (1 << 6) /* privilege exception */ +#define EXCEPT_CAUSE_RAX (1 << 5) /* resource access exception */ +#define EXCEPT_CAUSE_RCX (1 << 4) /* resource conflict exception */ +#define EXCEPT_CAUSE_OPX (1 << 3) /* opcode exception */ +#define EXCEPT_CAUSE_EPX (1 << 2) /* execute packet exception */ +#define EXCEPT_CAUSE_FPX (1 << 1) /* fetch packet exception */ +#define EXCEPT_CAUSE_IFX (1 << 0) /* instruction fetch exception */ + +enum SYSTEM_TRAP_CODE +{ + ABORT_BUS_ADDRERR = 0, // bus address error + ABORT_BUS_ACCERR, // bus access permission error + ABORT_OPCODE_ILL, // illegal opcode + ABORT_PRVREG_ILL, // privilege register + ABORT_PRVOPC_ILL, // privileged opcode + ABORT_ILLTRP_ILL, // illegal trap + ABORT_BRKPT_ILL, // handling breakpoints +}; + +/* + * abort types + */ +#define ABORT_TYPE_BUS 0 // bus access abnormal +#define ABORT_TYPE_MAP 1 // page table mapping error +#define ABORT_TYPE_UNDDEF 0xff // undefined exception +#define ABORT_TYPE_FATAL 0xffffffff // fatal error + +struct rt_exception_info { + char *kernel_str; + int type; + int code; +}; + +#define BKPT_OPCODE 0x56454314 /* illegal opcode */ +#define INTC_MEXPMASK __SYSREGA(0x018000e0, unsigned int) + +#define __ffs(a) (_lmbd(1, _bitr(a))) +#define fls(a) (!(a) ? 0 : (32 - _lmbd(1, (a)))) + +void rt_trap_init(void); + +#endif /* __TRAP_H__ */ + diff --git a/libcpu/ti-dsp/c6x/vector.asm b/libcpu/ti-dsp/c6x/vector.asm new file mode 100644 index 0000000000..47eb8781f5 --- /dev/null +++ b/libcpu/ti-dsp/c6x/vector.asm @@ -0,0 +1,95 @@ +; +; Copyright (c) 2021, Shenzhen Academy of Aerospace Technology +; +; SPDX-License-Identifier: Apache-2.0 +; +; Change Logs: +; Date Author Notes +; 2021-11-16 Dystopia the first version +; + +;----------------------------------------------------------- +; interrupt vector table for C6678 DSP +;----------------------------------------------------------- + +;----------------------------------------------------------- +; extern function +;----------------------------------------------------------- + .ref _c_int00 ; entry point + .ref _nmi_handler + .ref _bad_handler + .ref _int4_handler + .ref _int5_handler + .ref _int6_handler + .ref _int7_handler + .ref _int8_handler + .ref _int9_handler + .ref _int10_handler + .ref _int11_handler + .ref _int12_handler + .ref _int13_handler + .ref _int14_handler + .ref _int15_handler + +;----------------------------------------------------------- +; macro definition +;----------------------------------------------------------- + +; +; create interrupt vector for reset (interrupt 0) +; +VEC_RESET .macro addr + MVKL addr,B0 + MVKH addr,B0 + B B0 + MVC PCE1,B0 + NOP 4 + .align 32 + .endm + +; +; create interrupt vector for other used interrupts +; +IRQVEC .macro __name, __isr + .align 32 + .hidden __name + .global __name +__name: + B .S2 __isr + NOP + NOP + NOP + NOP + NOP + NOP + NOP + .endm +; +;----------------------------------------------------------- +; + +; +; vector table +; + .sect ".vecs" + .align 32 + .global vector +vector: + VEC_RESET _c_int00 + IRQVEC NMI, _nmi_handler + IRQVEC AINT, _bad_handler + IRQVEC MSGINT,_bad_handler + IRQVEC INT4, _int4_handler + IRQVEC INT5, _int5_handler + IRQVEC INT6, _int6_handler + IRQVEC INT7, _int7_handler + IRQVEC INT8, _int8_handler + IRQVEC INT9, _int9_handler + IRQVEC INT10, _int10_handler + IRQVEC INT11, _int11_handler + IRQVEC INT12, _int12_handler + IRQVEC INT13, _int13_handler + IRQVEC INT14, _int14_handler + IRQVEC INT15, _int15_handler + + .end From 456492e7eab69c7e9bb3feb2129dc5a905491efc Mon Sep 17 00:00:00 2001 From: Huang bo Date: Wed, 17 Nov 2021 17:43:42 +0800 Subject: [PATCH 02/24] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E6=94=AF=E6=8C=81?= =?UTF-8?q?=E4=B8=AD=E6=96=AD=E6=A0=88=E9=83=A8=E5=88=86=E4=BB=A3=E7=A0=81?= =?UTF-8?q?=EF=BC=8C=E4=BF=AE=E6=94=B9=E6=A0=BC=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- bsp/ti-c6678/applications/main.c | 99 - bsp/ti-c6678/driver/KeyStone_common.c | 4355 ----------------- bsp/ti-c6678/driver/KeyStone_common.h | 1090 ----- bsp/{ti-c6678 => ti-tms320c6678}/.ccsproject | 0 bsp/{ti-c6678 => ti-tms320c6678}/.cproject | 0 bsp/{ti-c6678 => ti-tms320c6678}/.project | 0 .../org.eclipse.cdt.codan.core.prefs | 0 .../org.eclipse.cdt.debug.core.prefs | 0 .../org.eclipse.core.resources.prefs | 0 bsp/{ti-c6678 => ti-tms320c6678}/KeyStone.cmd | 0 .../applications/board.c | 23 +- .../applications/board.h | 0 bsp/ti-tms320c6678/applications/main.c | 80 + .../driver/drv_timer.c | 0 .../driver/drv_timer.h | 0 bsp/ti-tms320c6678/readme.txt | 3 + bsp/{ti-c6678 => ti-tms320c6678}/rtconfig.h | 0 .../rtconfig_project.h | 0 libcpu/ti-dsp/c6x/c66xx.h | 5 +- libcpu/ti-dsp/c6x/context.asm | 52 +- libcpu/ti-dsp/c6x/contextinc.asm | 187 + libcpu/ti-dsp/c6x/cpuport.c | 30 +- libcpu/ti-dsp/c6x/interrupt.c | 1 - libcpu/ti-dsp/c6x/{inct.asm => intexc.asm} | 125 +- libcpu/ti-dsp/c6x/stack.asm | 6 +- libcpu/ti-dsp/c6x/trap.c | 12 +- libcpu/ti-dsp/c6x/trap.h | 4 +- libcpu/ti-dsp/c6x/vector.asm | 32 +- 28 files changed, 361 insertions(+), 5743 deletions(-) delete mode 100644 bsp/ti-c6678/applications/main.c delete mode 100644 bsp/ti-c6678/driver/KeyStone_common.c delete mode 100644 bsp/ti-c6678/driver/KeyStone_common.h rename bsp/{ti-c6678 => ti-tms320c6678}/.ccsproject (100%) rename bsp/{ti-c6678 => ti-tms320c6678}/.cproject (100%) rename bsp/{ti-c6678 => ti-tms320c6678}/.project (100%) rename bsp/{ti-c6678 => ti-tms320c6678}/.settings/org.eclipse.cdt.codan.core.prefs (100%) rename bsp/{ti-c6678 => ti-tms320c6678}/.settings/org.eclipse.cdt.debug.core.prefs (100%) rename bsp/{ti-c6678 => ti-tms320c6678}/.settings/org.eclipse.core.resources.prefs (100%) rename bsp/{ti-c6678 => ti-tms320c6678}/KeyStone.cmd (100%) rename bsp/{ti-c6678 => ti-tms320c6678}/applications/board.c (63%) rename bsp/{ti-c6678 => ti-tms320c6678}/applications/board.h (100%) create mode 100644 bsp/ti-tms320c6678/applications/main.c rename bsp/{ti-c6678 => ti-tms320c6678}/driver/drv_timer.c (100%) rename bsp/{ti-c6678 => ti-tms320c6678}/driver/drv_timer.h (100%) create mode 100644 bsp/ti-tms320c6678/readme.txt rename bsp/{ti-c6678 => ti-tms320c6678}/rtconfig.h (100%) rename bsp/{ti-c6678 => ti-tms320c6678}/rtconfig_project.h (100%) create mode 100644 libcpu/ti-dsp/c6x/contextinc.asm rename libcpu/ti-dsp/c6x/{inct.asm => intexc.asm} (69%) diff --git a/bsp/ti-c6678/applications/main.c b/bsp/ti-c6678/applications/main.c deleted file mode 100644 index fd418f09f4..0000000000 --- a/bsp/ti-c6678/applications/main.c +++ /dev/null @@ -1,99 +0,0 @@ -/* - * Copyright (c) 2021, Shenzhen Academy of Aerospace Technology - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - * 2021-11-16 Dystopia the first version - */ - -#include -#include - -#include "board.h" - -void rt_init_thread_entry(void *parameter) -{ - - while(1) - { - rt_thread_sleep(10); - } -} - -void rt_my_thread_entry(void *parameter) -{ - while(1) - { - rt_thread_sleep(20); - } -} - -int rt_application_init(void) -{ - rt_thread_t tid; - - tid = rt_thread_create("init", rt_init_thread_entry, RT_NULL, 4096, 3, 200); - if (tid != RT_NULL) - { - rt_thread_startup(tid); - } else { - return -1; - } - /******************************************************************/ - tid = rt_thread_create("mythread", rt_my_thread_entry, RT_NULL, 4096, 3, 200); - if (tid != RT_NULL) - { - rt_thread_startup(tid); - } else { - return -1; - } - - return 0; -} - -/** - * This function will startup RT-Thread RTOS. - */ -void rtthread_startup(void) -{ - /* disable interrupt first */ - rt_hw_interrupt_disable(); - - /* init board */ - rt_hw_board_init(); - - /* show version */ - rt_show_version(); - - /* init timer system */ - rt_system_timer_init(); - - /* init scheduler system */ - rt_system_scheduler_init(); - - /* init application */ - rt_application_init(); - - /* init timer thread */ - rt_system_timer_thread_init(); - - /* init idle thread */ - rt_thread_idle_init(); - - /* start scheduler */ - rt_system_scheduler_start(); - - /* never reach here */ - return ; -} - -void main(void) -{ - /* startup RT-Thread RTOS */ - rtthread_startup(); - - for ( ; ; ); -} - diff --git a/bsp/ti-c6678/driver/KeyStone_common.c b/bsp/ti-c6678/driver/KeyStone_common.c deleted file mode 100644 index 5807ed7aff..0000000000 --- a/bsp/ti-c6678/driver/KeyStone_common.c +++ /dev/null @@ -1,4355 +0,0 @@ -/****************************************************************************** - - Copyright (C), 2001-2012, Texas Instrument. - - ****************************************************************************** - File Name : KeyStone_common.c - Version : Initial Draft - Author : Brighton Feng - Created : 2010-12-12 - Last Modified : - Description : KeyStone common miscellaneous functions and definitions - History : - 1.Date : 2010-12-12 - Author : Brighton Feng - Modification: Created file - - 2.Date : 2012-10-6 - Author : Brighton Feng - Modification : Add memory protection and EDC configuration - - 3.Date : 2014-12-8 - Author : Brighton Feng - Modification : Add common device, CPU, interrupt initialization functions. - Print device information including device type, speed grade, - boot mode, required voltage, ID�� - Add EDMA enable/disable functions. - To support square wave generation by timer. -******************************************************************************/ - -#include -#include -#include -#include -#include -#include -#include -#include -#include "CSL_msmc.h" -#include "CSL_msmcAux.h" -#include "KeyStone_common.h" - -/*----------------------------------------------* - * external variables * - *----------------------------------------------*/ - -/*----------------------------------------------* - * external routine prototypes * - *----------------------------------------------*/ - -/*----------------------------------------------* - * internal routine prototypes * - *----------------------------------------------*/ - -/*----------------------------------------------* - * project-wide global variables * - *----------------------------------------------*/ -CSL_XmcRegs * gpXMC_regs = (CSL_XmcRegs *) CSL_XMC_CONFIG_REGS; -CSL_CgemRegs * gpCGEM_regs = (CSL_CgemRegs *)CSL_CGEM0_5_REG_BASE_ADDRESS_REGS; -CSL_BootcfgRegs * gpBootCfgRegs = (CSL_BootcfgRegs *)CSL_BOOT_CFG_REGS; -CSL_PllcRegs * gpPLLC_regs = (CSL_PllcRegs * )CSL_PLL_CONTROLLER_REGS; -CSL_PscRegs * gpPSC_regs = (CSL_PscRegs *)CSL_PSC_REGS; -CSL_MsmcRegs * gpMSMC_regs = (CSL_MsmcRegs *)CSL_MSMC_CONFIG_REGS; -CSL_GpioRegs * gpGPIO_regs= (CSL_GpioRegs * )CSL_GPIO_REGS; - -CSL_CPINTCRegs* gpCIC0_regs = (CSL_CPINTCRegs*)CSL_CP_INTC_0_REGS; -CSL_CPINTCRegs* gpCIC1_regs = (CSL_CPINTCRegs*)CSL_CP_INTC_1_REGS; -/*The register pointer for the CIC routing events DSP core. -By default, it is CIC0; but for core 4~7 of C6678, it is CIC1*/ -CSL_CPINTCRegs* gpCIC_regs= (CSL_CPINTCRegs*)CSL_CP_INTC_0_REGS; - -CSL_TpccRegs* gpEDMA_CC0_regs = (CSL_TpccRegs*)CSL_EDMA0CC_REGS; -CSL_TpccRegs* gpEDMA_CC1_regs = (CSL_TpccRegs*)CSL_EDMA1CC_REGS; -CSL_TpccRegs* gpEDMA_CC2_regs = (CSL_TpccRegs*)CSL_EDMA2CC_REGS; -CSL_TpccRegs* gpEDMA_CC_regs[3] = { - (CSL_TpccRegs*)CSL_EDMA0CC_REGS, - (CSL_TpccRegs*)CSL_EDMA1CC_REGS, - (CSL_TpccRegs*)CSL_EDMA2CC_REGS -}; - -CSL_TptcRegs * gpEDMA_TC_0_0_regs=(CSL_TptcRegs *) CSL_EDMA0TC0_REGS; -CSL_TptcRegs * gpEDMA_TC_0_1_regs=(CSL_TptcRegs *) CSL_EDMA0TC1_REGS; -CSL_TptcRegs * gpEDMA_TC_1_0_regs=(CSL_TptcRegs *) CSL_EDMA1TC0_REGS; -CSL_TptcRegs * gpEDMA_TC_1_1_regs=(CSL_TptcRegs *) CSL_EDMA1TC1_REGS; -CSL_TptcRegs * gpEDMA_TC_1_2_regs=(CSL_TptcRegs *) CSL_EDMA1TC2_REGS; -CSL_TptcRegs * gpEDMA_TC_1_3_regs=(CSL_TptcRegs *) CSL_EDMA1TC3_REGS; -CSL_TptcRegs * gpEDMA_TC_2_0_regs=(CSL_TptcRegs *) CSL_EDMA2TC0_REGS; -CSL_TptcRegs * gpEDMA_TC_2_1_regs=(CSL_TptcRegs *) CSL_EDMA2TC1_REGS; -CSL_TptcRegs * gpEDMA_TC_2_2_regs=(CSL_TptcRegs *) CSL_EDMA2TC2_REGS; -CSL_TptcRegs * gpEDMA_TC_2_3_regs=(CSL_TptcRegs *) CSL_EDMA2TC3_REGS; - -CSL_TptcRegs * gpEDMA_TC_regs[10]= { - (CSL_TptcRegs *) CSL_EDMA0TC0_REGS, - (CSL_TptcRegs *) CSL_EDMA0TC1_REGS, - (CSL_TptcRegs *) CSL_EDMA1TC0_REGS, - (CSL_TptcRegs *) CSL_EDMA1TC1_REGS, - (CSL_TptcRegs *) CSL_EDMA1TC2_REGS, - (CSL_TptcRegs *) CSL_EDMA1TC3_REGS, - (CSL_TptcRegs *) CSL_EDMA2TC0_REGS, - (CSL_TptcRegs *) CSL_EDMA2TC1_REGS, - (CSL_TptcRegs *) CSL_EDMA2TC2_REGS, - (CSL_TptcRegs *) CSL_EDMA2TC3_REGS -}; - -CSL_TmrPlusRegs * gpTimer0Regs = (CSL_TmrPlusRegs *)CSL_TIMER_0_REGS; -CSL_TmrPlusRegs * gpTimer1Regs = (CSL_TmrPlusRegs *)CSL_TIMER_1_REGS; -CSL_TmrPlusRegs * gpTimer2Regs = (CSL_TmrPlusRegs *)CSL_TIMER_2_REGS; -CSL_TmrPlusRegs * gpTimer3Regs = (CSL_TmrPlusRegs *)CSL_TIMER_3_REGS; -CSL_TmrPlusRegs * gpTimer4Regs = (CSL_TmrPlusRegs *)CSL_TIMER_4_REGS; -CSL_TmrPlusRegs * gpTimer5Regs = (CSL_TmrPlusRegs *)CSL_TIMER_5_REGS; -CSL_TmrPlusRegs * gpTimer6Regs = (CSL_TmrPlusRegs *)CSL_TIMER_6_REGS; -CSL_TmrPlusRegs * gpTimer7Regs = (CSL_TmrPlusRegs *)CSL_TIMER_7_REGS; -CSL_TmrPlusRegs * gpTimer8Regs = (CSL_TmrPlusRegs *)(CSL_TIMER_7_REGS+(CSL_TIMER_7_REGS-CSL_TIMER_6_REGS)); -CSL_TmrPlusRegs * gpTimerRegs[9] = { - (CSL_TmrPlusRegs *)CSL_TIMER_0_REGS, - (CSL_TmrPlusRegs *)CSL_TIMER_1_REGS, - (CSL_TmrPlusRegs *)CSL_TIMER_2_REGS, - (CSL_TmrPlusRegs *)CSL_TIMER_3_REGS, - (CSL_TmrPlusRegs *)CSL_TIMER_4_REGS, - (CSL_TmrPlusRegs *)CSL_TIMER_5_REGS, - (CSL_TmrPlusRegs *)CSL_TIMER_6_REGS, - (CSL_TmrPlusRegs *)CSL_TIMER_7_REGS, - (CSL_TmrPlusRegs *)(CSL_TIMER_7_REGS+(CSL_TIMER_7_REGS-CSL_TIMER_6_REGS)) -}; - -/*MPU for peripherals registers and data space*/ -CSL_MpuRegs * gpMPU0_regs= (CSL_MpuRegs *)CSL_MPU_0_REGS; -CSL_MpuRegs * gpMPU1_regs= (CSL_MpuRegs *)CSL_MPU_1_REGS; -CSL_MpuRegs * gpMPU2_regs= (CSL_MpuRegs *)CSL_MPU_2_REGS; -CSL_MpuRegs * gpMPU3_regs= (CSL_MpuRegs *)CSL_MPU_3_REGS; - -CSL_Emif4fRegs * gpDDR_regs= (CSL_Emif4fRegs *)CSL_DDR3_EMIF_CONFIG_REGS; -unsigned int gDSP_Core_Speed_Hz= 1000000000; //DSP core clock speed in Hz -TDSP_Board_Type gDSP_board_type= UNKNOWN; - -/*----------------------------------------------* - * module-wide global variables * - *----------------------------------------------*/ - -/*----------------------------------------------* - * constants * - *----------------------------------------------*/ - -/*----------------------------------------------* - * macros * - *----------------------------------------------*/ - -/*----------------------------------------------* - * routines' implementations * - *----------------------------------------------*/ - -/***************************************************************************** - Prototype : KeyStone_main_PLL_init - Description : DSP core PLL configuration - DSP core will be configured to run at ref_clock_MHz*multiplier/divisor - Input : float ref_clock_MHz - unsigned int multiplier: 1~4096 - unsigned int divisor: 1~64 - Output : - Return Value : - - History : - 1.Date : 2010-12-12 - Author : Brighton Feng - Modification : Created function - 2.Date : May 19, 2013 - Author : Brighton Feng - Modification : update parameter check; replace constant with macro - -*****************************************************************************/ -void KeyStone_main_PLL_init (float ref_clock_MHz, - unsigned int multiplier, unsigned int divisor) -{ - unsigned int i; - - if(0==divisor) - { - puts("Error: PLL input divider = 0"); - return; - } - - if(64SECCTL & PLLCTL_BYPASS_MASK) - { - /*a. In MAINPLLCTL1, write ENSAT = 1 (for optimal PLL operation) */ - gpBootCfgRegs->CORE_PLL_CTL1 |= PLLCTL1_ENSAT_MASK; /*Set ENSAT bit = 1*/ - - /*b. In PLLCTL, write PLLEN = 0 (bypass enabled in PLL controller mux) */ - gpPLLC_regs->PLLCTL &= ~CSL_PLLC_PLLCTL_PLLEN_MASK; - - /*c. In PLLCTL, write PLLENSRC = 0 (enable PLLEN to control PLL controller mux */ - gpPLLC_regs->PLLCTL &= ~CSL_PLLC_PLLCTL_PLLENSRC_MASK; - - /*d. Wait 4 cycles of the reference clock CLKIN (to make sure the PLL controller */ - /*mux switches properly to the bypass) */ - for(i=0; i< 4; i++) - asm(" nop 5"); - - /*e. In SECCTL, write BYPASS = 1 (bypass enabled in PLL mux) */ - gpPLLC_regs->SECCTL |= PLLCTL_BYPASS_MASK; - - /*f. In PLLCTL, write PLLPWRDN = 1 (power down the PLL) */ - gpPLLC_regs->PLLCTL |= CSL_PLLC_PLLCTL_PLLPWRDN_MASK; //Power down the PLL - - /*g. Wait for at least 5 ��s based on the reference clock CLKIN (PLL power down */ - /*toggling time) */ - for(i=0; i< 1000; i++) - asm(" nop 5"); - - /*h. In PLLCTL, write PLLPWRDN = 0 (power up the PLL) */ - gpPLLC_regs->PLLCTL &= ~CSL_PLLC_PLLCTL_PLLPWRDN_MASK; // Power up PLL - } - else - { - /*a. In PLLCTL, write PLLEN = 0 (bypass enabled in PLL controller mux) */ - gpPLLC_regs->PLLCTL &= (~CSL_PLLC_PLLCTL_PLLEN_MASK); - - /*b. In PLLCTL, write PLLENSRC = 0 (enable PLLEN to control PLL controller mux */ - gpPLLC_regs->PLLCTL &= (~CSL_PLLC_PLLCTL_PLLENSRC_MASK); - - /*c. Wait 4 cycles of the reference clock CLKIN (to make sure the PLL controller */ - /*mux switches properly to the bypass) */ - for(i=0; i< 4*multiplier/divisor; i++) - asm(" nop 5"); - } - - /*4. PLLM is split in two different registers. Program PLLM[5:0] in PLL multiplier */ - /*control register (PLLM) and PLLM[12:6] in MAINPLLCTL0 register */ - /*5. BWADJ is split in two different registers. Program BWADJ[7:0] in */ - /*MAINPLLCTL0 and BWADJ[11:8] in MAINPLLCTL1 register. BWADJ value */ - /*must be set to ((PLLM + 1) >> 1) - 1) */ - /*6. Program PLLD in MAINPLLCTL0 register */ - gpBootCfgRegs->CORE_PLL_CTL0 = ((multiplier-1)<PLLM= (multiplier*2-1)&0x3F; - gpBootCfgRegs->CORE_PLL_CTL1 &= ~PLLCTL1_BWADJ_MASK; - gpBootCfgRegs->CORE_PLL_CTL1 |= (multiplier-1)>>8; /*BWADJ[11:8]*/ - - /*7. In SECCTL, write OD (Output Divide) = 1 (that is divide-by-2) */ - gpPLLC_regs->SECCTL &= ~PLLCTL_OD_MASK; - gpPLLC_regs->SECCTL |= 1<PLLSTAT) & CSL_PLLC_PLLSTAT_GOSTAT_MASK); - - /* Step 8b: Program the RATIO field in PLLDIVn to the desired new divide-down rate. - If RATIO field is changed, the PLL controller will flag the change in the - corresponding bit of DCHANGE*/ - gpPLLC_regs->PLLDIV1_3[3-1] = (3-1) | CSL_PLLC_PLLDIV1_3_DNEN_MASK; //Set PLLDIV3 - gpPLLC_regs->PLLDIV4_16[4-4] = (5-1) | CSL_PLLC_PLLDIV4_16_DNEN_MASK; //Set PLLDIV4 - gpPLLC_regs->PLLDIV4_16[7-4] = (6-1) | CSL_PLLC_PLLDIV4_16_DNEN_MASK; //Set PLLDIV7 - - /* Step 8c: Set GOSET bit in PLLCMD to initiate the GO operation to change the divide - values and align the SYSCLKs as programmed */ - gpPLLC_regs->PLLCMD |= CSL_PLLC_PLLCMD_GOSET_MASK; - - /*Step 8d/e: Read the GOSTAT bit in PLLSTAT to make sure the bit returns to 0 to - indicate that the GO operation has completed */ - while((gpPLLC_regs->PLLSTAT) & CSL_PLLC_PLLSTAT_GOSTAT_MASK); -#endif - - /*9. In PLLCTL , write PLLRST = 1 (PLL reset is asserted)*/ - gpPLLC_regs->PLLCTL |= CSL_PLLC_PLLCTL_PLLRST_MASK; - - /*10. Wait for at least 7 ��s based on the reference clock CLKIN (PLL reset time) */ - for(i=0; i< 2000; i++) - asm(" nop 5"); - - /*11. In PLLCTL, write PLLRST = 0 (PLL reset is released) */ - gpPLLC_regs->PLLCTL &= ~CSL_PLLC_PLLCTL_PLLRST_MASK; - - /*12. Wait for at least 2000 �� CLKIN cycles �� (PLLD + 1) (PLL lock time) */ - for(i=0; i< 400*multiplier; i++) - asm(" nop 5"); - - /*13. In SECCTL, write BYPASS = 0 (enable PLL mux to switch to PLL mode) */ - gpPLLC_regs->SECCTL &= ~PLLCTL_BYPASS_MASK; - - /*14. Set the PLLEN bit in PLLCTL to 1 to enable PLL mode*/ - gpPLLC_regs->PLLCTL |= CSL_PLLC_PLLCTL_PLLEN_MASK; - -} -/***************************************************************************** - Prototype : KeyStone_PLL_init - Description : Config the PLL of PA and DDR - target clock speed will be ref_clock_MHz/inputDivisor*multiplier/outputDivisor - Input : unsigned int inputDivisor - unsigned int multiplier - unsigned int outputDivisor - Output : None - Return Value : 0 for success, other value for error - - History : - 1.Date : May 18, 2013 - Author : Brighton Feng - Modification : Created function - -*****************************************************************************/ -int KeyStone_PLL_init (PLL_ControlRegs * PLL_Regs, unsigned int inputDivisor, - unsigned int multiplier, unsigned int outputDivisor) -{ - if(0==inputDivisor) - { - puts("Error: PLL input divider = 0"); - return 1; - } - - if(64PLL_CTL1 = PLLCTL1_ENSAT_MASK; - - /*2. In PLLCTL0, write BYPASS = 1 (set the PLL in Bypass)*/ - PLL_Regs->PLL_CTL0 |= PLLCTL_BYPASS_MASK; - - /*3. Program PLLM and PLLD in PLLCTL0 register*/ - /*4. Program BWADJ[7:0] in PLLCTL0 and BWADJ[11:8] in PLLCTL1 register. - BWADJ value must be set to ((PLLM + 1) >> 1) �C 1)*/ - PLL_Regs->PLL_CTL0 = ((multiplier/2-1)<PLL_CTL1 &= ~PLLCTL1_BWADJ_MASK; - PLL_Regs->PLL_CTL1 |= (multiplier/2-1)>>8; /*BWADJ[11:8]*/ - - /*5. In PLLCTL1, write PLLRST = 1 (PLL is reset)*/ - PLL_Regs->PLL_CTL1 |= PLLCTL1_PLLRESET_MASK; //Set RESET bit = 1 - - /*6. Wait for at least 7 us based on the reference clock (PLL reset time)*/ - TSC_delay_us(7); - - /*For PASS, In PASSPLLCTL1, write PLLSELECT = 1 - (for selecting the output of PA PLL as the input to PASS)*/ - if(PLL_Regs==(PLL_ControlRegs *)gpBootCfgRegs->PA_PLL_CTL0) - PLL_Regs->PLL_CTL1 |= PLLCTL1_PAPLL_MASK; - - /*7. In PLLCTL1, write PLLRST = 0 (PLL reset is released)*/ - PLL_Regs->PLL_CTL1 &= ~PLLCTL1_PLLRESET_MASK; //Clear RESET bit - - /*8. Wait for at least 500 * REFCLK cycles * (PLLD + 1) (PLL lock time)*/ - TSC_delay_us(500); - - /*9. In PLLCTL0, write BYPASS = 0 (switch to PLL mode)*/ - PLL_Regs->PLL_CTL0 &= ~PLLCTL_BYPASS_MASK ; - - return 0; -} -/***************************************************************************** - Prototype : KeyStone_PASS_PLL_init - Description : Config the PASS PLL - target clock speed will be ref_clock_MHz/divisor*multiplier - Input : float ref_clock_MHz - unsigned int multiplier: 1~4096 - unsigned int divisor: 1~64 - Output : None - Return Value : - - History : - 1.Date : 2013-2-14 - Author : Brighton Feng - Modification : Created function - -*****************************************************************************/ -void KeyStone_PASS_PLL_init (float ref_clock_MHz, - unsigned int multiplier, unsigned int divisor) -{ - //output divisor for PASS PLL should be 2 - if(0==KeyStone_PLL_init((PLL_ControlRegs *)&gpBootCfgRegs->PA_PLL_CTL0, - divisor, multiplier*2, 2)) - { - printf("Initialize PASS PLL clock = %.2fMHz/%dx%d = %.3fMHz\n", - ref_clock_MHz, divisor, multiplier, - ref_clock_MHz*multiplier/divisor); - } -} - -/***************************************************************************** - Prototype : KeyStone_DDR_PLL_init - Description : Config the DDR PLL - target clock speed will be ref_clock_MHz/divisor*multiplier - Input : float ref_clock_MHz - unsigned int multiplier: 1~4096 - unsigned int divisor: 1~64 - Output : None - Return Value : - - History : - 1.Date : 2013-8-18 - Author : Brighton Feng - Modification : Created function - -*****************************************************************************/ -void KeyStone_DDR_PLL_init (float ref_clock_MHz, - unsigned int multiplier, unsigned int divisor) -{ - //output divisor for DDR PLL should be 2 - if(0==KeyStone_PLL_init((PLL_ControlRegs *)&gpBootCfgRegs->DDR3_PLL_CTL0, - divisor, multiplier, 2)) - { - printf("Initialize DDR speed = %.2fMHzx/%dx%d = %.3fMTS\n", - ref_clock_MHz, divisor, multiplier, - ref_clock_MHz*multiplier/divisor); - } -} - -/*===============================TSC===================================*/ -unsigned int cycle_measure_overhead=50; -/***************************************************************************** - Prototype : calc_cycle_measure_overhead - Description : calclucate the cycles measurement overhead - Input : None - Output : None - Return Value : - - History : - 1.Date : 2010/12/12 - Author : Brighton Feng - Modification : Created function - -*****************************************************************************/ -void calc_cycle_measure_overhead() -{ - unsigned int cycle_cold, cycle_warm; - cycle_cold= TSCL; - cycle_cold = TSC_getDelay(cycle_cold); - cycle_warm= TSCL; - cycle_warm = TSC_getDelay(cycle_warm); - cycle_measure_overhead = (cycle_cold + cycle_warm)/2; -} - -/***************************************************************************** - Prototype : TSC_init - Description : Initialize Time stamp counter to measure cycles - Input : None - Output : None - Return Value : - - History : - 1.Date : 2010/12/12 - Author : Brighton Feng - Modification : Created function - -*****************************************************************************/ -void TSC_init() -{ - TSCL = 0; /* Enable the TSC */ - calc_cycle_measure_overhead(); -} - -/***************************************************************************** - Prototype : TSC_delay_ms - Description : Implement the delay function in millisecond - Input : Uint32 ms - Output : None - Return Value : - - History : - 1.Date : 2010/12/12 - Author : Brighton Feng - Modification : Created function - -*****************************************************************************/ -void TSC_delay_ms(Uint32 ms) -{ - volatile unsigned long long startTSC, currentTSC; - unsigned long long delay_cycles; - Uint32 tscl, tsch; - - tscl= TSCL; - tsch= TSCH; - startTSC= _itoll(tsch,tscl); - - delay_cycles= ((unsigned long long)ms*gDSP_Core_Speed_Hz/1000); - - do - { - tscl= TSCL; - tsch= TSCH; - currentTSC= _itoll(tsch,tscl); - } - while((currentTSC-startTSC)TGCR) - { - gpTimerRegs[timer_num]->TGCR= 0; - gpTimerRegs[timer_num]->TCR= 0; - } -} - - /***************************************************************************** - Prototype : Timer64_Init - Description : Initialize a 64-bit timer - Input : Timer64_Config * tmrCfg - Output : None - Return Value : - - History : - 1.Date : 2010/12/12 - Author : Brighton Feng - Modification : Created function - -*****************************************************************************/ -void Timer64_Init(Timer64_Config * tmrCfg) -{ - Reset_Timer(tmrCfg->timer_num); - - gpTimerRegs[tmrCfg->timer_num]->CNTLO= 0; - gpTimerRegs[tmrCfg->timer_num]->CNTHI= 0; - - /*please note, in clock mode, two timer periods generate a clock, - one timer period output high voltage level, the other timer period - output low voltage level, so, the timer period should be half to the - desired output clock period*/ - if(TIMER_PERIODIC_CLOCK==tmrCfg->timerMode) - tmrCfg->period= tmrCfg->period/2; - - /*the value written into period register is the expected value minus one*/ - gpTimerRegs[tmrCfg->timer_num]->PRDLO= _loll(tmrCfg->period-1); - gpTimerRegs[tmrCfg->timer_num]->PRDHI= _hill(tmrCfg->period-1); - if(tmrCfg->reload_period>1) - { - gpTimerRegs[tmrCfg->timer_num]->RELLO= _loll(tmrCfg->reload_period-1); - gpTimerRegs[tmrCfg->timer_num]->RELHI= _hill(tmrCfg->reload_period-1); - } - - if(TIMER_WATCH_DOG==tmrCfg->timerMode) - { - gpTimerRegs[tmrCfg->timer_num]->TGCR= - /*Select watch-dog mode*/ - (CSL_TMR_TIMMODE_WDT<timerMode) - { - gpTimerRegs[tmrCfg->timer_num]->TGCR= TMR_TGCR_PLUSEN_MASK - /*for plus featuers, dual 32-bit unchained timer mode should be used*/ - |(CSL_TMR_TIMMODE_DUAL_UNCHAINED<timer_num]->INTCTL_STAT= TMR_INTCTLSTAT_EN_ALL_CLR_ALL; - } - else - { - gpTimerRegs[tmrCfg->timer_num]->TGCR= - /*Select 64-bit general timer mode*/ - (CSL_TMR_TIMMODE_GPT<timer_num]->EMUMGT_CLKSPD = (gpTimerRegs[tmrCfg->timer_num]->EMUMGT_CLKSPD& - ~(CSL_TMR_EMUMGT_CLKSPD_FREE_MASK|CSL_TMR_EMUMGT_CLKSPD_SOFT_MASK)); - - if(TIMER_WATCH_DOG==tmrCfg->timerMode) - { - /*enable watchdog timer*/ - gpTimerRegs[tmrCfg->timer_num]->WDTCR = CSL_TMR_WDTCR_WDEN_MASK - |(CSL_TMR_WDTCR_WDKEY_CMD1<timer_num]->TCR= - (CSL_TMR_CLOCK_INP_NOGATE<pulseWidth<timer_num]->WDTCR = CSL_TMR_WDTCR_WDEN_MASK - |(CSL_TMR_WDTCR_WDKEY_CMD2<timerMode) - { - gpTimerRegs[tmrCfg->timer_num]->TCR= - (CSL_TMR_CLOCK_INP_NOGATE<pulseWidth<timerMode) - { - gpTimerRegs[tmrCfg->timer_num]->TCR= - (CSL_TMR_CLOCK_INP_NOGATE<pulseWidth<timerMode) - { - gpTimerRegs[tmrCfg->timer_num]->TCR= - (CSL_TMR_CLOCK_INP_NOGATE<pulseWidth<timer_num]->TCR= - (CSL_TMR_CLOCK_INP_NOGATE<pulseWidth<WDTCR = - (CSL_TMR_WDTCR_WDKEY_CMD1<WDTCR = - (CSL_TMR_WDTCR_WDKEY_CMD2<0x3FFFFFFF) - { - printf("Enable power domain %d timeout!\n", pwrDmnNum); - return -2; - } - } - } - - /* Enable the clocks too*/ - CSL_PSC_setModuleNextState (moduleNum, PSC_MODSTATE_ENABLE); - - /* Start the state transition */ - CSL_PSC_startStateTransition (pwrDmnNum); - - /* Wait until the state transition process is completed. */ - while (!CSL_PSC_isStateTransitionDone (pwrDmnNum)) - { - if(TSC_count_cycle_from(uiStartTSC)>0x3FFFFFFF) - { - printf("Enable clock domain %d timeout!\n", moduleNum); - return -2; - } - } - - /* Return PSC status */ - if ((CSL_PSC_getPowerDomainState(pwrDmnNum) == PSC_PDSTATE_ON) && - (CSL_PSC_getModuleState (moduleNum) == PSC_MODSTATE_ENABLE)) - { - /*Ready for use */ - return 0; - } - else - { - /*Return error */ - return -1; - } -} -/***************************************************************************** - Prototype : KeyStone_disable_PSC_module - Description : Disable the PSC module in KeyStone device - Input : Uint32 pwrDmnNum - Uint32 moduleNum - Output : None - Return Value : - - History : - 1.Date : 2010/2/12 - Author : Brighton Feng - Modification : Created function - -*****************************************************************************/ -Int32 KeyStone_disable_PSC_module (Uint32 pwrDmnNum, Uint32 moduleNum) -{ - Uint32 uiStartTSC= TSCL; - - /* disable the clocks*/ - CSL_PSC_setModuleNextState (moduleNum, PSC_MODSTATE_SWRSTDISABLE); - - /* Start the state transition */ - CSL_PSC_startStateTransition (pwrDmnNum); - - /* Wait until the state transition process is completed. */ - while (!CSL_PSC_isStateTransitionDone (pwrDmnNum)) - { - if(TSC_count_cycle_from(uiStartTSC)>0x3FFFFFFF) - { - printf("Disable clock domain %d timeout!\n", moduleNum); - return -2; - } - } - - /* Return PSC status */ - if (CSL_PSC_getModuleState (moduleNum) == PSC_MODSTATE_SWRSTDISABLE) - { - /*Ready for use */ - return 0; - } - else - { - /*Return error */ - return -1; - } - -} -/***************************************************************************** - Prototype : KeyStone_disable_PSC_Power_Domain - Description : Disable the PSC power domain - Input : Uint32 pwrDmnNum - Output : None - Return Value : - - History : - 1.Date : 2010/12/12 - Author : Brighton Feng - Modification : Created function - -*****************************************************************************/ -Int32 KeyStone_disable_PSC_Power_Domain (Uint32 pwrDmnNum) -{ - Uint32 uiStartTSC= TSCL; - - /* Set Power domain to OFF */ - CSL_PSC_disablePowerDomain (pwrDmnNum); - - /* Start the state transition */ - CSL_PSC_startStateTransition (pwrDmnNum); - - /* Wait until the state transition process is completed. */ - while (!CSL_PSC_isStateTransitionDone (pwrDmnNum)) - { - if(TSC_count_cycle_from(uiStartTSC)>0x3FFFFFFF) - { - printf("Disable power domain %d timeout!\n", pwrDmnNum); - return -2; - } - } - - /* Return PSC status */ - if (CSL_PSC_getPowerDomainState(pwrDmnNum) == PSC_PDSTATE_OFF) - { - /*Ready for use */ - return 0; - } - else - { - /*Return error */ - return -1; - } - -} - -/*============================EDMA=====================================*/ - /***************************************************************************** - Prototype : EDMA_channel_TC_cfg - Description : Setup uiChannel of an EDMA to use uiTC - Input : Uint32 uiCC - Uint32 uiChannel - Uint32 uiTC - Output : None - Return Value : - - History : - 1.Date : 2010/12/12 - Author : Brighton Feng - Modification : Created function - -*****************************************************************************/ -void EDMA_channel_TC_cfg (Uint32 uiCC, - Uint32 uiChannel, Uint32 uiTC) -{ - gpEDMA_CC_regs[uiCC]->TPCC_DMAQNUM[uiChannel/8] = - (gpEDMA_CC_regs[uiCC]->TPCC_DMAQNUM[uiChannel/8]&(~(0xF<<((uiChannel&7)*4)))) - |(uiTC<<((uiChannel&7)*4)); -} -/***************************************************************************** - Prototype : EDMA_TC_priority_cfg - Description : Setup uiChannel of an EDMA TC priority - Input : Uint32 uiCC - Uint32 uiPri - Uint32 uiTC - Output : None - Return Value : - - History : - 1.Date : 2010/12/12 - Author : Brighton Feng - Modification : Created function - -*****************************************************************************/ -void EDMA_TC_priority_cfg(Uint32 uiCC, - Uint32 uiPri, Uint32 uiTC) -{ - gpEDMA_CC_regs[uiCC]->TPCC_QUEPRI= - (gpEDMA_CC_regs[uiCC]->TPCC_QUEPRI&(~(0xF<<((uiTC&3)*4)))) - |(uiPri<<((uiTC&3)*4)); -} -/***************************************************************************** - Prototype : EDMA_init - Description : Initialize all EDMA registers and clear the event - Input : None - Output : None - Return Value : - - History : - 1.Date : 2010/12/12 - Author : Brighton Feng - Modification : Created function - -*****************************************************************************/ -void EDMA_init () -{ - int i; - unsigned int * uipPaRAM; - - /*clear PaRAM*/ - uipPaRAM= (unsigned int *)&(gpEDMA_CC0_regs->PARAMSET[0]); - for(i=0; i<8*CSL_EDMA3_TPCC0_NUM_PARAMSETS; i++) - *uipPaRAM++=0; - - uipPaRAM= (unsigned int *)&(gpEDMA_CC1_regs->PARAMSET[0]); - for(i=0; i<8*CSL_EDMA3_TPCC1_NUM_PARAMSETS; i++) - *uipPaRAM++=0; - - uipPaRAM= (unsigned int *)&(gpEDMA_CC2_regs->PARAMSET[0]); - for(i=0; i<8*CSL_EDMA3_TPCC2_NUM_PARAMSETS; i++) - *uipPaRAM++=0; - - /*Assign PaRAM for different channels*/ - for(i=0; iTPCC_DCHMAP[i] = i<< CSL_TPCC_TPCC_DCHMAP0_PAENTRY_SHIFT; - - for(i=0; iTPCC_DCHMAP[i] = i<< CSL_TPCC_TPCC_DCHMAP0_PAENTRY_SHIFT; - - for(i=0; iTPCC_DCHMAP[i] = i<< CSL_TPCC_TPCC_DCHMAP0_PAENTRY_SHIFT; - - /*Assign TC/Queue for different channels*/ - gpEDMA_CC0_regs->TPCC_DMAQNUM[0]= 0x10101010; - gpEDMA_CC0_regs->TPCC_DMAQNUM[1]= 0x10101010; - - gpEDMA_CC1_regs->TPCC_DMAQNUM[0]= 0x32103210; - gpEDMA_CC1_regs->TPCC_DMAQNUM[1]= 0x32103210; - gpEDMA_CC1_regs->TPCC_DMAQNUM[2]= 0x32103210; - gpEDMA_CC1_regs->TPCC_DMAQNUM[3]= 0x32103210; - gpEDMA_CC1_regs->TPCC_DMAQNUM[4]= 0x32103210; - gpEDMA_CC1_regs->TPCC_DMAQNUM[5]= 0x32103210; - gpEDMA_CC1_regs->TPCC_DMAQNUM[6]= 0x32103210; - gpEDMA_CC1_regs->TPCC_DMAQNUM[7]= 0x32103210; - - gpEDMA_CC2_regs->TPCC_DMAQNUM[0]= 0x32103210; - gpEDMA_CC2_regs->TPCC_DMAQNUM[1]= 0x32103210; - gpEDMA_CC2_regs->TPCC_DMAQNUM[2]= 0x32103210; - gpEDMA_CC2_regs->TPCC_DMAQNUM[3]= 0x32103210; - gpEDMA_CC2_regs->TPCC_DMAQNUM[4]= 0x32103210; - gpEDMA_CC2_regs->TPCC_DMAQNUM[5]= 0x32103210; - gpEDMA_CC2_regs->TPCC_DMAQNUM[6]= 0x32103210; - gpEDMA_CC2_regs->TPCC_DMAQNUM[7]= 0x32103210; - - /*clear any events and status*/ - gpEDMA_CC0_regs->TPCC_ECR= 0xFFFF; - gpEDMA_CC0_regs->TPCC_EECR= 0xFFFF; - gpEDMA_CC0_regs->TPCC_ICR= 0xFFFF; - gpEDMA_CC0_regs->TPCC_IECR= 0xFFFF; - gpEDMA_CC0_regs->TPCC_EMCR= 0xFFFF; - gpEDMA_CC0_regs->TPCC_QEMCR= 0xFFFF; - gpEDMA_CC0_regs->TPCC_CCERRCLR= 0xFFFF; - gpEDMA_CC0_regs->TPCC_SECR= 0xFFFF; - - gpEDMA_CC1_regs->TPCC_ECR= 0xFFFFFFFF; - gpEDMA_CC1_regs->TPCC_ECRH= 0xFFFFFFFF; - gpEDMA_CC1_regs->TPCC_EECR= 0xFFFFFFFF; - gpEDMA_CC1_regs->TPCC_EECRH= 0xFFFFFFFF; - gpEDMA_CC1_regs->TPCC_ICR= 0xFFFFFFFF; - gpEDMA_CC1_regs->TPCC_ICRH= 0xFFFFFFFF; - gpEDMA_CC1_regs->TPCC_IECR= 0xFFFFFFFF; - gpEDMA_CC1_regs->TPCC_IECRH= 0xFFFFFFFF; - gpEDMA_CC1_regs->TPCC_EMCR= 0xFFFFFFFF; - gpEDMA_CC1_regs->TPCC_EMCRH= 0xFFFFFFFF; - gpEDMA_CC1_regs->TPCC_QEMCR= 0xFFFFFFFF; - gpEDMA_CC1_regs->TPCC_CCERRCLR= 0xFFFF; - gpEDMA_CC1_regs->TPCC_SECR= 0xFFFFFFFF; - gpEDMA_CC1_regs->TPCC_SECRH= 0xFFFFFFFF; - - gpEDMA_CC2_regs->TPCC_ECR= 0xFFFFFFFF; - gpEDMA_CC2_regs->TPCC_ECRH= 0xFFFFFFFF; - gpEDMA_CC2_regs->TPCC_EECR= 0xFFFFFFFF; - gpEDMA_CC2_regs->TPCC_EECRH= 0xFFFFFFFF; - gpEDMA_CC2_regs->TPCC_ICR= 0xFFFFFFFF; - gpEDMA_CC2_regs->TPCC_ICRH= 0xFFFFFFFF; - gpEDMA_CC2_regs->TPCC_IECR= 0xFFFFFFFF; - gpEDMA_CC2_regs->TPCC_IECRH= 0xFFFFFFFF; - gpEDMA_CC2_regs->TPCC_EMCR= 0xFFFFFFFF; - gpEDMA_CC2_regs->TPCC_EMCRH= 0xFFFFFFFF; - gpEDMA_CC2_regs->TPCC_QEMCR= 0xFFFFFFFF; - gpEDMA_CC2_regs->TPCC_CCERRCLR= 0xFFFF; - gpEDMA_CC2_regs->TPCC_SECR= 0xFFFFFFFF; - gpEDMA_CC2_regs->TPCC_SECRH= 0xFFFFFFFF; - - for(i=0; iTPTC_ERRCLR= 0xF; - - //enable error interrupt - gpEDMA_TC_regs[i]->TPTC_ERREN= - (1<TPCC_EESR= 1<<(uiChannel); - } - else - { - //enable the EDMA channel - gpEDMA_CC_regs[uiCC]->TPCC_EESRH= 1<<(uiChannel-32); - } -} - -void EDMA_event_disable(Uint32 uiCC, Uint32 uiChannel) -{ - if(uiChannel<32) - { - //disable the EDMA channel - gpEDMA_CC_regs[uiCC]->TPCC_EECR= 1<<(uiChannel); - } - else - { - //disable the EDMA channel - gpEDMA_CC_regs[uiCC]->TPCC_EECRH= 1<<(uiChannel-32); - } -} - -void EDMA_interrupt_enable(Uint32 uiCC, Uint32 uiIntNum) -{ - if(uiIntNum<32) - { - //enable the EDMA channel interrupt - gpEDMA_CC_regs[uiCC]->TPCC_IESR= 1<<(uiIntNum); - } - else - { - //enable the EDMA channel interrupt - gpEDMA_CC_regs[uiCC]->TPCC_IESRH= 1<<(uiIntNum-32); - } -} - -void EDMA_interrupt_disable(Uint32 uiCC, Uint32 uiIntNum) -{ - if(uiIntNum<32) - { - //disable the EDMA channel interrupt - gpEDMA_CC_regs[uiCC]->TPCC_IECR= 1<<(uiIntNum); - } - else - { - //disable the EDMA channel interrupt - gpEDMA_CC_regs[uiCC]->TPCC_IECRH= 1<<(uiIntNum-32); - } -} - -/***************************************************************************** - Prototype : EDMA_wait - Description : wait the pending EDMA complete - Input : EDMA_CC_Channel_Num CC_channel - Output : None - Return Value : - - History : - 1.Date : 2012/10/30 - Author : Brighton Feng - Modification : Created function - -*****************************************************************************/ -void EDMA_wait(EDMA_CC_Channel_Num CC_channel) -{ - CSL_TpccRegs* EDMACCRegs; - unsigned int uiChannel; - volatile Uint32 * TPCC_IPR; - volatile Uint32 * TPCC_ICR; - - EDMACCRegs= gpEDMA_CC_regs[CC_channel>>16]; - uiChannel = CC_channel&0xFF; - - if(uiChannel<32) - { - TPCC_IPR= &EDMACCRegs->TPCC_IPR; - TPCC_ICR= &EDMACCRegs->TPCC_ICR; - } - else - { - TPCC_IPR= &EDMACCRegs->TPCC_IPRH; - TPCC_ICR= &EDMACCRegs->TPCC_ICRH; - uiChannel -= 32; - } - - /*wait for completion*/ - while(0==((*TPCC_IPR)&(1<<(uiChannel)))); - - /*clear completion flag*/ - (*TPCC_ICR)= 1<<(uiChannel); -} - -/***************************************************************************** - Prototype : EDMA_Copy - Description : EDMA copy function with manual trigger - Input : unsigned int srcAddr - unsigned int dstAddr - unsigned int byteCount, <64KB - EDMA_CC_Channel_Num CC_channel - DMA_Wait wait - Output : None - Return Value : - - History : - 1.Date : 2012/10/30 - Author : Brighton Feng - Modification : Created function - -*****************************************************************************/ -void EDMA_copy(unsigned int srcAddr, unsigned int dstAddr, - unsigned int byteCount, EDMA_CC_Channel_Num CC_channel, DMA_Wait wait) -{ - CSL_TpccRegs* EDMACCRegs; - unsigned int uiChannel; - volatile Uint32 * TPCC_ESR; - volatile Uint32 * TPCC_IPR; - volatile Uint32 * TPCC_ICR; - - EDMACCRegs= gpEDMA_CC_regs[CC_channel>>16]; - uiChannel = CC_channel&0xFF; - - EDMACCRegs->PARAMSET[uiChannel].OPT= - CSL_EDMA3_OPT_MAKE(CSL_EDMA3_ITCCH_DIS, - CSL_EDMA3_TCCH_DIS, - CSL_EDMA3_ITCINT_DIS, - CSL_EDMA3_TCINT_EN, - uiChannel, - CSL_EDMA3_TCC_NORMAL, - CSL_EDMA3_FIFOWIDTH_NONE, - CSL_EDMA3_STATIC_DIS, - CSL_EDMA3_SYNC_A, - CSL_EDMA3_ADDRMODE_INCR, - CSL_EDMA3_ADDRMODE_INCR); - EDMACCRegs->PARAMSET[uiChannel].SRC= GLOBAL_ADDR(srcAddr); - EDMACCRegs->PARAMSET[uiChannel].A_B_CNT=CSL_EDMA3_CNT_MAKE(byteCount&0xFFFF, 1); - EDMACCRegs->PARAMSET[uiChannel].DST= GLOBAL_ADDR(dstAddr); - EDMACCRegs->PARAMSET[uiChannel].SRC_DST_BIDX= 0; - EDMACCRegs->PARAMSET[uiChannel].LINK_BCNTRLD= CSL_EDMA3_LINKBCNTRLD_MAKE(0xFFFF, 1); - EDMACCRegs->PARAMSET[uiChannel].SRC_DST_CIDX= 0; - EDMACCRegs->PARAMSET[uiChannel].CCNT= 1; - - if(uiChannel<32) - { - TPCC_ESR= &EDMACCRegs->TPCC_ESR; - TPCC_IPR= &EDMACCRegs->TPCC_IPR; - TPCC_ICR= &EDMACCRegs->TPCC_ICR; - } - else - { - TPCC_ESR= &EDMACCRegs->TPCC_ESRH; - TPCC_IPR= &EDMACCRegs->TPCC_IPRH; - TPCC_ICR= &EDMACCRegs->TPCC_ICRH; - uiChannel -= 32; - } - - /*Manually trigger the EDMA*/ - (*TPCC_ESR)= 1<<(uiChannel); - - if(wait) - { - /*wait for completion*/ - while(0==((*TPCC_IPR)&(1<<(uiChannel)))); - - /*clear completion flag*/ - (*TPCC_ICR)= 1<<(uiChannel); - } -} - -/***************************************************************************** - Prototype : EDMA_fill - Description : EDMA fill function with manual trigger - Input : unsigned int address, must align to 8 bytes boundary - unsigned long long data - unsigned int byteCount, must be multiple of 8 - EDMA_CC_Channel_Num CC_channel - Output : None - Return Value : - - History : - 1.Date : 2013/8/11 - Author : Brighton Feng - Modification : Created function - -*****************************************************************************/ -void EDMA_fill(unsigned int address, unsigned long long data, - unsigned int byteCount, EDMA_CC_Channel_Num CC_channel) -{ - int i; - CSL_TpccRegs* EDMACCRegs; - unsigned int uiChannel, uiChannelShift, uiBCNT; - volatile Uint32 * TPCC_ESR; - volatile Uint32 * TPCC_IPR; - volatile Uint32 * TPCC_ICR; - unsigned long long tempBuf[128/8]; - Uint32 tempBufSize=128, headerSize, tailSize; - - if(tempBufSize>byteCount) - tempBufSize=byteCount; - - for(i=0; i< tempBufSize/8; i++) - tempBuf[i]= data; - - /*split the transfer into 3 sections at 128 byte boundary*/ - if(address&127) //header address not start on 128 byte boundary - { - headerSize= 128- (address&127); - if(headerSize>byteCount) - headerSize=byteCount; - EDMA_copy((Uint32)tempBuf, address, headerSize, CC_channel, DMA_WAIT); - address+= headerSize; - byteCount-= headerSize; - } - - if(byteCount&&((address+byteCount)&127))//tail address not start on 128 byte boundary - { - tailSize= (address+byteCount)&127; - EDMA_copy((Uint32)tempBuf, address+byteCount-tailSize, tailSize, CC_channel, DMA_WAIT); - byteCount-= tailSize; - } - - EDMACCRegs= gpEDMA_CC_regs[CC_channel>>16]; - uiChannel = CC_channel&0xFF; - if(uiChannel<32) - { - TPCC_ESR= &EDMACCRegs->TPCC_ESR; - TPCC_IPR= &EDMACCRegs->TPCC_IPR; - TPCC_ICR= &EDMACCRegs->TPCC_ICR; - uiChannelShift= uiChannel; - } - else - { - TPCC_ESR= &EDMACCRegs->TPCC_ESRH; - TPCC_IPR= &EDMACCRegs->TPCC_IPRH; - TPCC_ICR= &EDMACCRegs->TPCC_ICRH; - uiChannelShift= uiChannel - 32; - } - - EDMACCRegs->PARAMSET[uiChannel].OPT= - CSL_EDMA3_OPT_MAKE(CSL_EDMA3_ITCCH_DIS, - CSL_EDMA3_TCCH_DIS, - CSL_EDMA3_ITCINT_DIS, - CSL_EDMA3_TCINT_EN, - uiChannel, - CSL_EDMA3_TCC_NORMAL, - CSL_EDMA3_FIFOWIDTH_NONE, - CSL_EDMA3_STATIC_EN, //keep PARAM unchanged - CSL_EDMA3_SYNC_AB, - CSL_EDMA3_ADDRMODE_INCR, - CSL_EDMA3_ADDRMODE_INCR); - EDMACCRegs->PARAMSET[uiChannel].SRC= GLOBAL_ADDR(tempBuf); - EDMACCRegs->PARAMSET[uiChannel].SRC_DST_BIDX= CSL_EDMA3_BIDX_MAKE(0, 128); - EDMACCRegs->PARAMSET[uiChannel].LINK_BCNTRLD= CSL_EDMA3_LINKBCNTRLD_MAKE(0xFFFF, 0); - EDMACCRegs->PARAMSET[uiChannel].SRC_DST_CIDX= 0; - EDMACCRegs->PARAMSET[uiChannel].CCNT= 1; - - while(byteCount) //the reminding must be multiple of 128 bytes - { - uiBCNT= byteCount/128; - if(uiBCNT>65535) - uiBCNT= 65535; - - EDMACCRegs->PARAMSET[uiChannel].A_B_CNT= CSL_EDMA3_CNT_MAKE(128, uiBCNT); - EDMACCRegs->PARAMSET[uiChannel].DST= GLOBAL_ADDR(address); - - /*Manually trigger the EDMA*/ - (*TPCC_ESR)= 1<<(uiChannelShift); - - /*wait for completion*/ - while(0==((*TPCC_IPR)&(1<<(uiChannelShift)))); - - /*clear completion flag*/ - (*TPCC_ICR)= 1<<(uiChannelShift); - - byteCount -= uiBCNT*128; - address += uiBCNT*128; - } -} - -/***************************************************************************** - Prototype : IDMA_wait - Description : wait the pending IDMA complete - Input : None - Output : None - Return Value : - - History : - 1.Date : 2012/10/28 - Author : Brighton Feng - Modification : Created function - -*****************************************************************************/ -void IDMA_wait() -{ - /* Wait until copying is completed */ - while (gpCGEM_regs->IDMA1_STAT); -} -/***************************************************************************** - Prototype : IDMA_copy - Description : implement the data copy via IDMA - Input : unsigned int srcAddr - unsigned int dstAddr - unsigned int byteCount, <64KB - IDMA_Wait wait - Output : None - Return Value : - - History : - 1.Date : 2012/10/28 - Author : Brigthon - Modification : Created function - -*****************************************************************************/ -void IDMA_copy(unsigned int srcAddr, unsigned int dstAddr, - unsigned int byteCount, DMA_Wait wait) -{ - gpCGEM_regs->IDMA1_SOURCE= srcAddr; - gpCGEM_regs->IDMA1_DEST= dstAddr; - gpCGEM_regs->IDMA1_COUNT= byteCount&0xFFFC; - - if(wait) - { - /* Wait until copying is completed */ - while (gpCGEM_regs->IDMA1_STAT); - } -} -/***************************************************************************** - Prototype : EDMA_CC_error_handler - Description : Edma channel controller error processing - Input : Uint32 edmaNum, EDMA module number (0~2) - Output : None - Return Value : - - History : - 1.Date : 2012/11/7 - Author : Brighton Feng - Modification : Created function - -*****************************************************************************/ -void EDMA_CC_error_handler(Uint32 edmaNum) -{ - int i; - CSL_TpccRegs* EDMACCRegs= gpEDMA_CC_regs[edmaNum]; - Uint32 EMR, EMRH= 0, QEMR, CCERR; - - //read error status - EMR= EDMACCRegs->TPCC_EMR; - QEMR= EDMACCRegs->TPCC_QEMR; - CCERR= EDMACCRegs->TPCC_CCERR; - exception_record.status.ext_sts.info.edma.CC_info.EMR= EMR; - exception_record.status.ext_sts.info.edma.CC_info.QEMR= QEMR; - exception_record.status.ext_sts.info.edma.CC_info.CCERR= CCERR; - - //clear error status - EDMACCRegs->TPCC_EMCR= EMR; - EDMACCRegs->TPCC_QEMCR= QEMR; - EDMACCRegs->TPCC_CCERRCLR= CCERR; - - //channel 32~63 for EDMA CC1 and CC2 - if(0TPCC_EMRH; - exception_record.status.ext_sts.info.edma.CC_info.EMRH= EMRH; - - //clear error status - EDMACCRegs->TPCC_EMCRH= EMRH; - } - - for(i=0; i<32; i++) - { - if((EMR>>i)&1) - printf(" EDMA Channel %d event missed.\n", i); - if((EMRH>>i)&1) - printf(" EDMA Channel %d event missed.\n", i+32); - } - - for(i=0; i<8; i++) - { - if((QEMR>>i)&1) - printf(" QDMA Channel %d event missed.\n", i); - } - - for(i=0; i<4; i++) - { - if((CCERR>>i)&1) - printf(" Queue %d Watermark/threshold has been exceeded.\n", i); - } - - if(CCERR&CSL_TPCC_TPCC_CCERR_TCCERR_MASK) - puts(" Total number of allowed TCCs has been reached."); - -} -/***************************************************************************** - Prototype : EDMA_TC_error_handler - Description : Edma transfer controller error processing - Input : CSL_TptcRegs * edmaTCRegs - Output : None - Return Value : - - History : - 1.Date : 2012/11/7 - Author : Brighton Feng - Modification : Created function - -*****************************************************************************/ -void EDMA_TC_error_handler(CSL_TptcRegs * edmaTCRegs) -{ - Uint32 ERRSTAT, ERRDET, STAT; - - //read error status - ERRSTAT= edmaTCRegs->TPTC_ERRSTAT; - ERRDET= edmaTCRegs->TPTC_ERRDET; - exception_record.status.ext_sts.info.edma.TC_info.ERRSTAT=ERRSTAT ; - exception_record.status.ext_sts.info.edma.TC_info.ERRDET= ERRDET; - - //clear error - edmaTCRegs->TPTC_ERRCLR= ERRSTAT; - - if(ERRSTAT&CSL_TPTC_TPTC_ERRSTAT_MMRAERR_MASK) - puts(" User attempted to read or write to an invalid address in configuration memory map."); - if(ERRSTAT&CSL_TPTC_TPTC_ERRSTAT_TRERR_MASK) - puts(" TR detected that violates constant addressing mode transfer (SAM or DAM is set) alignment rules or has ACNT or BCNT== 0."); - if(ERRSTAT&CSL_TPTC_TPTC_ERRSTAT_BUSERR_MASK) - { - puts(" EDMA3TC has detected an error at source or destination address."); - - STAT= ERRDET&CSL_TPTC_TPTC_ERRDET_STAT_MASK; - - if(STAT>=8) - printf(" write error (%d). ",STAT); - else if(STAT>=1) - printf(" read error (%d). ",STAT); - else - printf(" no error!?"); - - printf("TCC= %d. TCINTEN= %d. TCCHEN= %d\n", - (ERRDET&CSL_TPTC_TPTC_ERRDET_TCC_MASK)>>CSL_TPTC_TPTC_ERRDET_TCC_SHIFT, - (ERRDET&CSL_TPTC_TPTC_ERRDET_TCINTEN_MASK)>>CSL_TPTC_TPTC_ERRDET_TCINTEN_SHIFT, - (ERRDET&CSL_TPTC_TPTC_ERRDET_TCCHEN_MASK)>>CSL_TPTC_TPTC_ERRDET_TCCHEN_SHIFT); - } - -} -/***************************************************************************** - Prototype : EDMA_error_handler - Description : EDMA error processing function - Input : Uint32 edmaNum - Uint32 errorFlag - error flag bit fields are defined as below - (follow the sequence in CIC) - 0 EDMACC_ERRINT EDMA3CC error interrupt - 2 EDMATC_ERRINT0 EDMA3TC0 error interrupt - 3 EDMATC_ERRINT1 EDMA3TC1 error interrupt - 4 EDMATC_ERRINT2 EDMA3TC2 error interrupt - 5 EDMATC_ERRINT3 EDMA3TC3 error interrupt - Output : None - Return Value : - - History : - 1.Date : 2012/10/28 - Author : Brighton Feng - Modification : Created function - -*****************************************************************************/ -void EDMA_error_handler(Uint32 edmaNum, Uint32 errorFlag) -{ - int i; - - printf(" EDMA module %d error\n", edmaNum); - if(errorFlag&1) - EDMA_CC_error_handler(edmaNum); - - errorFlag >>= 2; - - for(i=0; i<4; i++) - { - if(errorFlag&(1<MPLKCMD = (1<MPLK[i] = mem_prot_key[i]; - } - - /*3. Write a 1 to the LOCK field of the MPLKCMD register. This engages the lock.*/ - gpCGEM_regs->MPLKCMD = (1<MPLKSTAT&CSL_CGEM_MPLKSTAT_LK_MASK)); -} - -/***************************************************************************** - Prototype : unlock_mem_prot_regs - Description : unlock memory protection registers - Input : None - Output : None - Return Value : - - History : - 1.Date : 2010/12/12 - Author : Brighton Feng - Modification : Created function - -*****************************************************************************/ -#pragma CODE_SECTION (unlock_mem_prot_regs, ".text:Core_MPAX") -void unlock_mem_prot_regs() -{ - int i; - - /*1. Write a 1 to the KEYR field in the MPLKCMD register. This resets some internal - status for the MPLK0 through the MPLK3 registers.*/ - gpCGEM_regs->MPLKCMD = (1<MPLK[i] = mem_prot_key[i]; - } - - /*3. Write a 1 to the UNLOCK field in the MPLKCMD register. If the key written in - step 2 matches the stored key, the hardware disengages the lock. If the key written - in step 2 does not match, the hardware signals an exception. The hardware - reports the fault address as the address of the MPLKCMD register.*/ - gpCGEM_regs->MPLKCMD = (1<MPLKSTAT&CSL_CGEM_MPLKSTAT_LK_MASK)); -} - -/***************************************************************************** - Prototype : L1_MPPA_setup - Description : setup the memory protection for local L1 memory - Input : volatile Uint32 MPPA_regs[], Uint32 MPPA[] - Output : None - Return Value : - -usage example: - Uint32 MPPA[16]= - { - MP_LOCAL|MP_SR|MP_UR, //page 0 for read only - MP_LOCAL|MP_SR|MP_SW|MP_UR|MP_UW, //page 1 for read/write - ...... - } - ...... - L1_MPPA_setup(gpCGEM_regs->L1PMPPA, MPPA); - - History : - 1.Date : 2012/12/6 - Author : Brighton Feng - Modification : Created function - -*****************************************************************************/ -void L1_MPPA_setup(volatile Uint32 MPPA_regs[], Uint32 MPPA[]) -{ - int i; - - if(gpCGEM_regs->MPLKSTAT&CSL_CGEM_MPLKSTAT_LK_MASK) - unlock_mem_prot_regs(); - - /*clear any memory protection fault*/ - gpCGEM_regs->L1PMPFCR = 1; - gpCGEM_regs->L1DMPFCR = 1; - - /*setup the memory protection attributes for 32 pages*/ - for(i=0; i<16; i++) - { - MPPA_regs[i] = MPPA[i]; - } - - lock_mem_prot_regs(); -} - -/***************************************************************************** - Prototype : L1P_memory_protection_cfg - Description : config "AccessPermisionMask" for L1P - Input : Uint32 AccessPermisionMask - Output : None - Return Value : -*****************************************************************************/ -void L1P_memory_protection_cfg(Uint32 AccessPermisionMask) -{ - int i; - - if(gpCGEM_regs->MPLKSTAT&CSL_CGEM_MPLKSTAT_LK_MASK) - unlock_mem_prot_regs(); - - /*clear any memory protection fault*/ - gpCGEM_regs->L1PMPFCR = 1; - - /*set L1P only for cacheable local execution, disable all external access*/ - for(i=0; i<16; i++) - { - gpCGEM_regs->L1PMPPA[i] = AccessPermisionMask; - } - - lock_mem_prot_regs(); -} - -/***************************************************************************** - Prototype : L1D_memory_protection_cfg - Description : config "AccessPermisionMask" for L1P - Input : Uint32 AccessPermisionMask - Output : None - Return Value : -*****************************************************************************/ -void L1D_memory_protection_cfg(Uint32 AccessPermisionMask) -{ - int i; - - if(gpCGEM_regs->MPLKSTAT&CSL_CGEM_MPLKSTAT_LK_MASK) - unlock_mem_prot_regs(); - - /*clear any memory protection fault*/ - gpCGEM_regs->L1DMPFCR = 1; - - /*set L1P only for cacheable local execution, disable all external access*/ - for(i=0; i<16; i++) - { - gpCGEM_regs->L1DMPPA[i] = AccessPermisionMask; - } - - lock_mem_prot_regs(); -} - -/***************************************************************************** - Prototype : L1_cache_protection - Description : protect L1 as cache - Input : None - Output : None - Return Value : - - History : - 1.Date : 2012/10/28 - Author : Brighton Feng - Modification : Created function - -*****************************************************************************/ -void L1_cache_protection() -{ - /*set L1P only for cacheable local execution, disable all external access*/ - L1P_memory_protection_cfg(0); - - /*set L1D only for cacheable local read/write, disable all external access*/ - L1D_memory_protection_cfg(0); -} - - -/***************************************************************************** - Prototype : LL2_MPPA_setup - Description : setup the memory protection for local L2 memory - Input : Uint32 MPPA[] - Output : None - Return Value : -usage example: - Uint32 MPPA[32]= - { - MP_LOCAL|MP_SX|MP_UX, //page 0 for local code only - MP_LOCAL|MP_SR|MP_SW|MP_UR|MP_UW, //page 1 for local data only - ...... - } - ...... - LL2_MPPA_setup(MPPA); - - History : - 1.Date : 2012/10/5 - Author : Brighton Feng - Modification : Created function - -*****************************************************************************/ -void LL2_MPPA_setup(Uint32 MPPA[]) -{ - int i; - - if(gpCGEM_regs->MPLKSTAT&CSL_CGEM_MPLKSTAT_LK_MASK) - unlock_mem_prot_regs(); - - /*clear any memory protection fault*/ - gpCGEM_regs->L2MPFCR = 1; - - /*setup the memory protection attributes for 32 pages*/ - for(i=0; i<32; i++) - { - gpCGEM_regs->L2MPPA[i] = MPPA[i]; - } - - lock_mem_prot_regs(); -} - -/***************************************************************************** - Prototype : LL2_Memory_Protection_cfg - Description : config "AccessPermisionMask" for local L2 memory section from - "startAddress" with "byteCount" size - Input : Uint32 startAddress - Uint32 byteCount - Uint32 AccessPermisionMask - Output : None - Return Value : - - History : - 1.Date : 2012/10/5 - Author : Brighton Feng - Modification : Created function - -*****************************************************************************/ -void LL2_Memory_Protection_cfg(Uint32 startAddress, - Uint32 byteCount, Uint32 AccessPermisionMask) -{ - int i; - Uint32 uiEndAddress; - Uint32 uiPageIndex, uiNumPages, uiPageSize, uiPageAddressMask, uiPageShift; - TDSP_Board_Type DSP_Board_Type; - - if(gpCGEM_regs->MPLKSTAT&CSL_CGEM_MPLKSTAT_LK_MASK) - unlock_mem_prot_regs(); - - DSP_Board_Type = KeyStone_Get_dsp_board_type(); - - /*L2 memory protection size is 32KB for TCI6614, C6670, - it is 16KB for C6678*/ - uiPageSize= 32*1024; - uiPageAddressMask= 32*1024-1; - uiPageShift= 15; - if(C6678_EVM == DSP_Board_Type) - { - uiPageSize= 16*1024; - uiPageAddressMask= 16*1024-1; - uiPageShift= 14; - } - - if(startAddress>=0x10800000) - { - printf("LL2 memory protection start Address 0x%x is not a local address\n", - startAddress); - startAddress &= 0xFFFFFF; /*convert to local address*/ - } - uiEndAddress= startAddress+ byteCount; - - if(startAddress&uiPageAddressMask) - { - printf("LL2 memory protection start Address 0x%x does not align to page boundary\n", - startAddress); - startAddress &= (~uiPageAddressMask); - } - uiPageIndex= (startAddress-0x800000)>>uiPageShift; - - byteCount= uiEndAddress- startAddress; - if(byteCount&uiPageAddressMask) - { - printf("LL2 memory protection section size 0x%x is not multiple of page size\n", - byteCount); - byteCount = (byteCount+uiPageSize)&(~uiPageAddressMask); - } - uiNumPages= byteCount>>uiPageShift; - - for(i= 0; iL2MPPA[uiPageIndex+i] = AccessPermisionMask; - - lock_mem_prot_regs(); -} - -/***************************************************************************** - Prototype : KeyStone_CorePac_AID_map - Description : map CorePac AID to PrivID: - map_table[0] assign the PrivID for AID0, - map_table[1] assign the PrivID for AID1 - ...... - map_table[5] assign the PrivID for AID5 - Input : Uint8 map_table[] - Output : None - Return Value : - - History : - 1.Date : 2012/10/5 - Author : Zhan - Modification : Created function - -*****************************************************************************/ -void KeyStone_CorePac_AID_map(Uint8 map_table[]) -{ - int i; - Uint32 *PAMAP= (Uint32 *)&(gpCGEM_regs->PAMAP0); - - /*map all PrivID to AIDx by default*/ - for(i=0; i<16; i++) - PAMAP[i]= CSL_CGEM_PAMAP0_AID_MASK; - - /*map AID0~AID5*/ - for(i=0; i<6; i++) - { - if(map_table[i]<16) /*PrivID must be less than 16*/ - PAMAP[map_table[i]]= i; - } -} - -/***************************************************************************** - Prototype : KeyStone_PrivID_Remap - Description : privilege ID remap to AID - Input : int privID - int AID - Output : None - Return Value : - - History : - 1.Date : 2012/10/5 - Author : Zhan - Modification : Created function - -*****************************************************************************/ -void KeyStone_PrivID_Remap(int privID, int AID) -{ - volatile unsigned int * pamapReg = NULL; - unsigned int val = 0; - - pamapReg = (volatile unsigned int *)(&gpCGEM_regs->PAMAP0 + privID); - - if(AID >= MAX_AID_NUM) - AID = 0; - val = *pamapReg; - - val &= (~CSL_CGEM_PAMAP0_AID_MASK); - - val |= ((AID<>4)) - { - printf("Segment replacement address 0x%x does not start from power-of-2 boundary corresponds to segment size 0x%x.\n", - RADDR, SegementSize); - RADDR &= (~(SegSizeMask>>4)); - printf("Extended replacement address to 0x%x.\n", RADDR); - } - - MPAX_regs->MPAXH= BADDR|(SegSizeBits-1); - MPAX_regs->MPAXL= RADDR|AccessPermisionMask; - -} - -/***************************************************************************** - Prototype : KeyStone_XMC_MPAX_setup - Description : configure multiple MPAX segments in XMC with a configuration - table. - Please note, the code of this function or the data used by this function - (stack, parameters...) can not be put in the segment that will be modified - by this function. Normally, to put this function and its related data in - LL2 is a good idea. - Input : MPAX_Config MPAX_cfg[] - Uint32 firstSeg - Uint32 numSegs - Output : None - Return Value : - - History : - 1.Date : 2012/10/15 - Author : Brighton Feng - Modification : Created function - -*****************************************************************************/ -#pragma CODE_SECTION (KeyStone_XMC_MPAX_setup, ".text:Core_MPAX") -void KeyStone_XMC_MPAX_setup(MPAX_Config MPAX_cfg[], - Uint32 firstSeg, Uint32 numSegs) -{ - int i; - - if(firstSeg >= 16) - { - printf("The XMC MPAX segment number %d >= 16, not supported.\n ", firstSeg); - return; - } - - if(gpCGEM_regs->MPLKSTAT&CSL_CGEM_MPLKSTAT_LK_MASK) - unlock_mem_prot_regs(); - - /*CAUTION: - A MPAX segment can only be modified when there is no access to the space - of this segment. Any data in cache or prefetch buffer from the space of this - segment must be writeback and invalidated before the segment modification. - It is recommended to configure the MPAX at the very beginning of application - software before any shared memory is used. Code and data for CorePac MPAX - configuration should be allocated in LL2. - If a MPAX segment must be modified on-the-fly, the safer way is, to write - the new configuration to a unused higher segment, and then clear the old - segment. This is based on the fact that higher numbered segments take - precedence over lower numbered segments. */ - CACHE_wbInvAllL2(CACHE_WAIT); - CSL_XMC_invalidatePrefetchBuffer(); - _mfence(); - _mfence(); //ensure all writeback invalidate have completed. - - for(i=numSegs-1; i>=0 ; i--) - { - KeyStone_MPAX_seg_setup((MPAX_Regs *)&gpXMC_regs->XMPAX[firstSeg+i], - MPAX_cfg[i].BADDR, MPAX_cfg[i].RADDR, - MPAX_cfg[i].SegementSize, MPAX_cfg[i].AccessPermisionMask); - } - - lock_mem_prot_regs(); -} - -/***************************************************************************** - Prototype : KeyStone_SMS_MPAX_setup - Description : configure multiple MPAX segments in SMS of MSMC with a conf- - iguration table - Input : MPAX_Config MPAX_cfg[] - Uint32 firstSeg - Uint32 numSegs - Uint32 PrivID - Output : None - Return Value : - - History : - 1.Date : 2012/10/15 - Author : Brighton Feng - Modification : Created function - -*****************************************************************************/ -void KeyStone_SMS_MPAX_setup(MPAX_Config MPAX_cfg[], - Uint32 firstSeg, Uint32 numSegs, Uint32 PrivID) -{ - int i; - - if( gpMSMC_regs->SMS_MPAX_LCKSTAT&(1<=0 ; i--) - KeyStone_MPAX_seg_setup( - (MPAX_Regs *)&gpMSMC_regs->SMS_MPAX_PER_PRIVID[PrivID].SMS[firstSeg+i], - MPAX_cfg[i].BADDR, MPAX_cfg[i].RADDR, - MPAX_cfg[i].SegementSize, MPAX_cfg[i].AccessPermisionMask); - - CSL_MSMC_lockSMS(PrivID); -} - -/***************************************************************************** - Prototype : KeyStone_SES_MPAX_setup - Description : configure multiple MPAX segments in SES of MSMC with a conf- - iguration table - Input : MPAX_Config MPAX_cfg[] - Uint32 firstSeg - Uint32 numSegs - Uint32 PrivID - Output : None - Return Value : - - History : - 1.Date : 2012/10/15 - Author : Brighton Feng - Modification : Created function - -*****************************************************************************/ -void KeyStone_SES_MPAX_setup(MPAX_Config MPAX_cfg[], - Uint32 firstSeg, Uint32 numSegs, Uint32 PrivID) -{ - int i; - - if( gpMSMC_regs->SES_MPAX_LCKSTAT&(1<=0 ; i--) - KeyStone_MPAX_seg_setup( - (MPAX_Regs *)&gpMSMC_regs->SES_MPAX_PER_PRIVID[PrivID].SES[firstSeg+i], - MPAX_cfg[i].BADDR, MPAX_cfg[i].RADDR, - MPAX_cfg[i].SegementSize, MPAX_cfg[i].AccessPermisionMask); - - CSL_MSMC_lockSES(PrivID); -} - -/***************************************************************************** - Prototype : KeyStone_MSMC_MP_interrupt_en - Description : Enable MSMC Memory protection error interrupt for PrivIDs - indicated by "PRIVID_MASK" - Input : Uint32 PRIVID_MASK - Output : None - Return Value : - - History : - 1.Date : 2012/10/15 - Author : Zhan - Modification : Created function - -*****************************************************************************/ -void KeyStone_MSMC_MP_interrupt_en(Uint32 PRIVID_MASK) -{ - if(gpMSMC_regs->CFGLCKSTAT&CSL_MSMC_CFGLCKSTAT_WSTAT_MASK) - CSL_MSMC_unlockNonMPAX(); - - /*clear MP fault record*/ - gpMSMC_regs->SMPFCR = 1; - - /*clear interrupt error status flag*/ - gpMSMC_regs->SMIRC = (PRIVID_MASK)<SMIESTAT |= (PRIVID_MASK<> - CSL_CGEM_L2MPFSR_FID_SHIFT; - - printf(" memory protection exception caused by master with ID %d at 0x%x\n", - master_id, MPFAR); - } - - if (MPFSR & CSL_CGEM_L2MPFSR_UX_MASK) { - puts(" User Execute violation"); - } - if (MPFSR & CSL_CGEM_L2MPFSR_UW_MASK) { - puts(" User Write violation"); - } - if (MPFSR & CSL_CGEM_L2MPFSR_UR_MASK) { - puts(" User Read violation"); - } - if (MPFSR & CSL_CGEM_L2MPFSR_SX_MASK) { - puts(" Supervisor Execute violation"); - } - if (MPFSR & CSL_CGEM_L2MPFSR_SW_MASK) { - puts(" Supervisor Write violation"); - } - if (MPFSR & CSL_CGEM_L2MPFSR_SR_MASK) { - puts(" Supervisor Read violation"); - } - -} - -/***************************************************************************** - Prototype : KeyStone_MSMC_protection_exception_handler - Description : MSMC memory protection processing - Input : None - Output : None - Return Value : -*****************************************************************************/ -void KeyStone_MSMC_protection_exception_handler() -{ - unsigned int master_id; - unsigned int priv_id; - unsigned int address; - unsigned int NM; - - address = gpMSMC_regs->SMPFAR; - - master_id = (gpMSMC_regs->SMPFR&CSL_MSMC_SMPFR_FMSTID_MASK)>> - CSL_MSMC_SMPFR_FMSTID_SHIFT; - priv_id = (gpMSMC_regs->SMPFR&CSL_MSMC_SMPFR_FPID_MASK)>> - CSL_MSMC_SMPFR_FPID_SHIFT; - - exception_record.status.ext_sts.info.memory.fault_address= address; - exception_record.status.ext_sts.info.memory.fault_status.SMPFR= gpMSMC_regs->SMPFR; - - NM = (gpMSMC_regs->SMPFXR & CSL_MSMC_SMPFXR_NM_MASK) >> CSL_MSMC_SMPFXR_NM_SHIFT; - - printf(" memory protection exception caused by master %d (PrivID= %d) at address 0x%x\n", - master_id, priv_id, address); - - if(1 == NM) - { - printf(" Fault is caused by the address not matching any of the segment BADDR\n"); - } - - if(gpMSMC_regs->CFGLCKSTAT&CSL_MSMC_CFGLCKSTAT_WSTAT_MASK) - CSL_MSMC_unlockNonMPAX(); - /*clear fault record*/ - gpMSMC_regs->SMPFCR = 1; - /*clear interrupt error status flag*/ - gpMSMC_regs->SMIRC = (1<PROG_START_ADDRESS = uiStartAddress; - MPPA_regs->PROG_END_ADDRESS = uiEndAddress; - MPPA_regs->PROG_MPPA = AccessPermisionMask; -} - -/***************************************************************************** - Prototype : KeyStone_MPU_setup - Description : peripherals MPU ranges configuration - Input : Uint32 uiMPU_num: number of the MPU to be setup - MPU_Range_Config MPU_cfg[]: MPU ranges configuration table - Uint32 numRangeCfg: number of ranges to be configured - Output : None - Return Value : - - History : - 1.Date : 2012/12/15 - Author : Brighton Feng - Modification : Created function -*****************************************************************************/ -void KeyStone_MPU_setup(Uint32 uiMPU_num, - MPU_Range_Config MPU_cfg[], Uint32 numRangeCfg) -{ - int i; - unsigned int mpuNumProgmableRange; - CSL_MpuRegs * mpuRegs; - - /*For Turbo Nyquist, add following code to modify initial value, - Or user can modify the initail values directly*/ - if(5==uiMPU_num) - TN_MPU5_constant(); - - mpuRegs= gpMPU_regs[uiMPU_num]; - - mpuNumProgmableRange = (mpuRegs->CONFIG & CSL_MPU_CONFIG_NUM_PROG_MASK)>>CSL_MPU_CONFIG_NUM_PROG_SHIFT; - if(mpuNumProgmableRange == 0) - { - mpuNumProgmableRange = 16; - } - - if(numRangeCfg>mpuNumProgmableRange) - { - printf("MPU %d programmable ranges %d < %d.\n", - uiMPU_num, mpuNumProgmableRange, numRangeCfg); - numRangeCfg=mpuNumProgmableRange; - } - else if(numRangeCfg gstruMpuAddrRange[uiMPU_num].EndAddr) ) - { - printf("The configuration address is out of MPU %d protection range\n", - uiMPU_num); - continue; - } - - KeyStone_MPU_range_setup(&mpuRegs->PROG_REGION[i], - MPU_cfg[i].StartAddr, MPU_cfg[i].EndAddr, - MPU_cfg[i].AccessPermisionMask); - - } - - //clear unused ranges - for( ;iPROG_REGION[i].PROG_MPPA = 0; - } - - //clear status - mpuRegs->FAULT_CLEAR = 1; - mpuRegs->INT_ENABLED_STATUS_CLEAR = - CSL_MPU_INT_ENABLED_STATUS_CLEAR_ENABLED_ADDR_ERR_MASK - |CSL_MPU_INT_ENABLED_STATUS_CLEAR_ENABLED_PROT_ERR_MASK; - - /* enable the interrupt */ - mpuRegs->INT_ENABLE = CSL_MPU_INT_ENABLE_ADDR_ERR_EN_MASK - | CSL_MPU_INT_ENABLE_PROT_ERR_EN_MASK; - - return; -} - -/***************************************************************************** - Prototype : KeyStone_MPU_MPPA_modify - Description : search the range which match a address and then modify - the access permission of that range. - Input : Uint32 uiMPU_num: number of the MPU to be modifed - Uint32 uiAddress: address which need modify permision - Uint32 AccessPermisionMask: permission mask for that range - Output : None - Return Value : - - History : - 1.Date : 2012/12/13 - Author : Brighton Feng - Modification : Created function -*****************************************************************************/ -void KeyStone_MPU_MPPA_modify(Uint32 uiMPU_num, - Uint32 uiAddress, Uint32 AccessPermisionMask) -{ - int i; - unsigned int mpuNumProgmableRange; - CSL_MpuRegs * mpuRegs; - - /*For Turbo Nyquist, add following code to modify initial value, - Or user can modify the initail values directly*/ - if(5==uiMPU_num) - TN_MPU5_constant(); - - mpuRegs= gpMPU_regs[uiMPU_num]; - - mpuNumProgmableRange = (mpuRegs->CONFIG & CSL_MPU_CONFIG_NUM_PROG_MASK)>>CSL_MPU_CONFIG_NUM_PROG_SHIFT; - if(mpuNumProgmableRange == 0) - { - mpuNumProgmableRange = 16; - } - - /*search through all ranges*/ - for(i=0; i< mpuNumProgmableRange; i++) - { - /*match with one range*/ - if((uiAddress >= mpuRegs->PROG_REGION[i].PROG_START_ADDRESS) - &&(uiAddress <= mpuRegs->PROG_REGION[i].PROG_END_ADDRESS)) - { - mpuRegs->PROG_REGION[i].PROG_MPPA = AccessPermisionMask; - return; - } - } - - printf("address 0x%08x does not match any range in MPU %d\n", - uiAddress, uiMPU_num); - - return; -} - -/***************************************************************************** - Prototype : KeyStone_MPU_interrupts_enable - Description : enable the all MPU interrupts - Input : None - Output : None - Return Value : - - History : - 1.Date : 2012/10/28 - Author : Brighton Feng - Modification : Created function - -*****************************************************************************/ -void KeyStone_MPU_interrupt_enable(Uint32 uiMPU_num) -{ - if((gpMPU_regs[uiMPU_num]->REVISION&0xFFFF0000)!= - (CSL_MPU_REVISION_RESETVAL&0xFFFF0000)) - { - printf("Can't read MPU%d ID register, make sure corresponding power domain is enabled.", uiMPU_num); - return; - } - - gpMPU_regs[uiMPU_num]->FAULT_CLEAR = 1; - gpMPU_regs[uiMPU_num]->INT_ENABLED_STATUS_CLEAR = - CSL_MPU_INT_ENABLED_STATUS_CLEAR_ENABLED_ADDR_ERR_MASK - |CSL_MPU_INT_ENABLED_STATUS_CLEAR_ENABLED_PROT_ERR_MASK; - gpMPU_regs[uiMPU_num]->INT_ENABLE = CSL_MPU_INT_ENABLE_ADDR_ERR_EN_MASK - |CSL_MPU_INT_ENABLE_PROT_ERR_EN_MASK; - -} -void KeyStone_MPU_interrupts_enable() -{ - int i; - TDSP_Board_Type DSP_Board_Type = KeyStone_Get_dsp_board_type(); - - TN_MPU5_constant(); - - for(i=0; i<4; i++) - { - KeyStone_MPU_interrupt_enable(i); - } - - if((C6670_EVM== DSP_Board_Type) - ||(TCI6614_EVM== DSP_Board_Type)) - { - for(i=4; i<6; i++) - { - /*MPU5 (for BCP) of TCI6614 is only accessible - when BCP is enabled through PSC*/ - if((5==i)&&(TCI6614_EVM== DSP_Board_Type)&& - ((CSL_PSC_getPowerDomainState(5) != PSC_PDSTATE_ON) || - (CSL_PSC_getModuleState (12) != PSC_MODSTATE_ENABLE))) - { - puts("Enable power domain for MPU5 before configure it."); - continue; - } - - KeyStone_MPU_interrupt_enable(i); - } - } - - if(TCI6614_EVM== DSP_Board_Type) - { - for(i=6; i<8; i++) - { - KeyStone_MPU_interrupt_enable(i); - } - } - - return; -} - -char * Peri_MPU_err_type_str[]= -{ - "User execution fault!", - "User write fault!", - "User read fault!", - "Supervisor execution fault!", - "Supervisor write fault!", - "Supervisor read fault!" -}; - -char * Ns_str[]= -{ - "secure", - "non-secure" -}; -/***************************************************************************** - Prototype : KeyStone_peripherals_MPU_fault_status - Description : Print the MPU error information - Input : unsigned int uwFltStatus - unsigned int uwFltAddr - Output : None - Return Value : -*****************************************************************************/ -void KeyStone_peripherals_MPU_fault_status(unsigned int uwFltStatus, - unsigned int uwFltAddr) -{ - unsigned int MSTID; - unsigned int PRIVID; - unsigned int NS; - unsigned int FaultType; - unsigned int BitsCnt; - - MSTID = (uwFltStatus & CSL_MPU_FAULT_STATUS_MSTID_MASK)>>CSL_MPU_FAULT_STATUS_MSTID_SHIFT; - PRIVID = (uwFltStatus & CSL_MPU_FAULT_STATUS_PRIVID_MASK)>>CSL_MPU_FAULT_STATUS_PRIVID_SHIFT; - NS = (uwFltStatus & CSL_MPU_FAULT_STATUS_NS_MASK)>>CSL_MPU_FAULT_STATUS_NS_SHIFT; - printf(" The MSTID %d (PRIVID %d) triggered MPU error at 0x%x with %s access\n", - MSTID, PRIVID, uwFltAddr, Ns_str[NS]); - - FaultType = (uwFltStatus & CSL_MPU_FAULT_STATUS_FAULT_TYPE_MASK) >> CSL_MPU_FAULT_STATUS_FAULT_TYPE_SHIFT; - if(1==(_dotpu4(_bitc4(FaultType), 0x01010101))) - { - BitsCnt= 31 - _lmbd(1, FaultType); - printf(" %s\n",Peri_MPU_err_type_str[BitsCnt]); - } - else if(0x3F == FaultType) - { - puts(" Relaxed cache line fill fault!"); - } - else if(0x12 == FaultType) - { - puts(" Relaxed cache write back fault!"); - } -} -/***************************************************************************** - Prototype : KeyStone_peripherals_MPU_excepiton_handler - Description : peripheral MPU processing - Input : Uint32 uwMpuNum - Output : None - Return Value : -*****************************************************************************/ -void KeyStone_peripherals_MPU_excepiton_handler(Uint32 uwMpuNum) -{ - Uint32 uwStatus; - Uint32 uwFltAddr; - Uint32 uwFltStatus; - CSL_MpuRegs *pstruMpuRegs= gpMPU_regs[uwMpuNum]; - - uwStatus = pstruMpuRegs->INT_ENABLED_STATUS_CLEAR; - if(uwStatus & 0x2) - { - printf(" MPU %d address violation error\n", uwMpuNum); - pstruMpuRegs->INT_ENABLED_STATUS_CLEAR = 2; - } - - if(uwStatus & 0x1) - { - printf(" MPU %d protection violation error\n", uwMpuNum); - pstruMpuRegs->INT_ENABLED_STATUS_CLEAR = 1; - } - - uwFltAddr = pstruMpuRegs->FAULT_ADDRESS; - uwFltStatus = pstruMpuRegs->FAULT_STATUS; - exception_record.status.ext_sts.info.memory.fault_address= uwFltAddr; - exception_record.status.ext_sts.info.memory.fault_status.MPU_FAULT_STATUS= uwFltStatus; - - KeyStone_peripherals_MPU_fault_status(uwFltStatus,uwFltAddr); - pstruMpuRegs->FAULT_CLEAR = 1; - - pstruMpuRegs->EOI = 0; -} - - -/*======================memory EDC=====================================*/ -/***************************************************************************** - Prototype : KeyStone_SL2_EDC_enable - Description : Enable MSMC EDC - Input : scrubCnt, number of MSMC clock cycles between scrubbing - Output : None - Return Value : - - History : - 1.Date : 2012/10/15 - Author : Brighton Feng - Modification : Created function - -*****************************************************************************/ -void KeyStone_SL2_EDC_enable(Uint32 scrubCnt) -{ - if(gpMSMC_regs->CFGLCKSTAT&CSL_MSMC_CFGLCKSTAT_WSTAT_MASK) - CSL_MSMC_unlockNonMPAX(); - - /*Software must wait for the PRR (Parity RAM Ready) bit before making - the first read access to MSMC RAM after reset.*/ - while(0==(gpMSMC_regs->SMEDCC&CSL_MSMC_SMEDCC_PRR_MASK)); - - /* set scrubbing period value */ - if(scrubCnt>255) - scrubCnt= 255; - CSL_MSMC_setCounterBankRefreshRead(scrubCnt); //the scrubbing engine works every scrubCnt*1024 cycle*/ - - /* clear EDC errors and enable EDC event*/ - gpMSMC_regs->SMIRC = 0xf; - gpMSMC_regs->SMIESTAT |= (CSL_MSMC_SMIESTAT_NCSIE_MASK - | CSL_MSMC_SMIESTAT_CSIE_MASK - | CSL_MSMC_SMIESTAT_NCEIE_MASK - | CSL_MSMC_SMIESTAT_CEIE_MASK); - - //enable SL2 EDC - CSL_MSMC_setECM(1); - - CSL_MSMC_lockNonMPAX(); -} - -/***************************************************************************** - Prototype : KeyStone_SL2_EDC_interrupt_en - Description : Enable MSMC EDC error interrupt - Input : None - Output : None - Return Value : - - History : - 1.Date : 2012/10/15 - Author : Brighton Feng - Modification : Created function - -*****************************************************************************/ -void KeyStone_SL2_EDC_interrupt_en() -{ - if(gpMSMC_regs->CFGLCKSTAT&CSL_MSMC_CFGLCKSTAT_WSTAT_MASK) - CSL_MSMC_unlockNonMPAX(); - - /* clear EDC errors*/ - gpMSMC_regs->SMIRC = 0xf; - - /* Enable EDC error interrupt */ - gpMSMC_regs->SMIESTAT |= (CSL_MSMC_SMIESTAT_NCSIE_MASK - | CSL_MSMC_SMIESTAT_CSIE_MASK - | CSL_MSMC_SMIESTAT_NCEIE_MASK - | CSL_MSMC_SMIESTAT_CEIE_MASK); - - CSL_MSMC_lockNonMPAX(); -} - -/***************************************************************************** - Prototype : LL2_EDC_setup - Description : Eenable LL2 EDC and scrub whole LL2 - Input : None - Output : None - Return Value : - - History : - 1.Date : 2012/10/10 - Author : Jane - Modification : Created function - - 2.Date : 2012/10/20 - Author : Brighton Feng - -*****************************************************************************/ -void LL2_EDC_setup() -{ - int i; - unsigned int uiByteCnt= 512*1024; - TDSP_Board_Type DSP_Board_Type; - - /* 1. Disable the EDC */ - CSL_CGEM_disableL2EDC(); - - /* 2. Clear any EDC errors */ - CSL_CGEM_clearL2EDCErrorStatus(1, 1, 1, 1); - - /* 3. Memory Scrubbing with IDMA, generate the parity bits*/ - DSP_Board_Type = KeyStone_Get_dsp_board_type(); - if((DUAL_NYQUIST_EVM == DSP_Board_Type) - ||(C6670_EVM == DSP_Board_Type) - ||(TCI6614_EVM == DSP_Board_Type)) - { - uiByteCnt= 1024*1024; - } - - /*Each IDMA can transfer up to 65532 bytes, - here we transfer 32KB each time*/ - for(i=0; i< (uiByteCnt>>15); i++) - { - IDMA_copy((0x00800000 + i*(1<<15)), (0x00800000 + i*(1<<15)), - (1<<15), DMA_WAIT); - } - - /* 4. Enable the EDC*/ - CSL_CGEM_enableL2EDC(); - gpCGEM_regs->L2EDCEN= (1<= uiLL2EndAddress) - uiLL2_scrub_addr=0x800000; - -} - -/***************************************************************************** - Prototype : L1P_EDC_setup - Description : enable L1P ED and scrub whole L1P - Input : None - Output : None - Return Value : - - History : - 1.Date : 2012/10/10 - Author : Jane - Modification : Created function - - 2.Date : 2012/10/30 - Author : Brighton Feng -*****************************************************************************/ -void L1P_EDC_setup() -{ - Uint32 preL1PMPPA[16]; - - /* 1. Disable the EDC */ - CSL_CGEM_disablePMCErrorDetection(); - - /* 2. Clear any EDC errors */ - CSL_CGEM_clearPMCErrorDetectionStatus(1, 1); - - /* 3. Memory Scrubbing with IDMA, generate the parity bits*/ - memcpy(preL1PMPPA, (void *)gpCGEM_regs->L1PMPPA, 64);//save protection attributes - L1P_memory_protection_cfg(0xFFFF); //enable IDMA access to L1P - IDMA_copy(0x00E00000, 0x00E00000, 32*1024, DMA_WAIT); - L1_MPPA_setup(gpCGEM_regs->L1PMPPA, preL1PMPPA);//restore protection for L1 - - /* 4. Enable the EDC*/ - CSL_CGEM_enablePMCErrorDetection(); -} - -char * LL2_EDC_victim_err_str="LL2 victims"; -char * LL2_EDC_DMA_err_str= "DMA access"; -char * LL2_EDC_L1D_err_str= "L1D access"; -char * LL2_EDC_L1P_err_str= "L1P access"; - -/***************************************************************************** - Prototype : LL2_EDC_handler - Description : LL2 EDC exception/interrupt handler - Input : None - Output : None - Return Value : - - History : - 1.Date : 2012/10/28 - Author : Brighton Feng - Modification : Created function - -*****************************************************************************/ -void LL2_EDC_handler(Bool bCorrected) -{ - /* EDC error during the L1D access */ - Uint8 derr; - /* EDC error during the L1P access */ - Uint8 perr; - /* EDC error during the DMA access*/ - Uint8 dmaerr; - /* EDC error during the L2 victim occurred */ - Uint8 verr; - /* single bit or dual bit EDC error */ - Uint8 nerr; - - char *errStr; - Uint32 errAddr; - - /* Get the all LL2 error status */ - CSL_CGEM_getL2EDCErrorStatus(&derr, &perr, &dmaerr, &verr, &nerr); - - if(derr|perr|dmaerr|verr) - { - errAddr= gpCGEM_regs->L2EDADDR&CSL_CGEM_L2EDADDR_ADDR_MASK; - - exception_record.status.ext_sts.info.memory.fault_address= errAddr; - exception_record.status.ext_sts.info.memory.fault_status.L2EDSTAT= - gpCGEM_regs->L2EDSTAT; - - if(bCorrected) - { - printf(" LL2 EDC (correctable) at bit %d of ",(gpCGEM_regs->L2EDSTAT& - CSL_CGEM_L2EDSTAT_BITPOS_MASK)>>CSL_CGEM_L2EDSTAT_BITPOS_SHIFT); - - //scrub 64 bytes including the error address to correct the error - if(perr) //by L1P access - IDMA_copy(errAddr&0xFFFFFFC0, errAddr&0xFFFFFFC0, 64, DMA_WAIT); - else - { - volatile Uint32 * uipAddress= (volatile Uint32 *)(errAddr&0xFFFFFFC0); - /*read one word into a cache line, and write to make it dirty, - which will be automatically written back sooner or later*/ - *uipAddress= *uipAddress; - } - } - else - { - printf(" LL2 EDC error (non-correctable) at "); - } - errStr = (char *)(perr * (Uint32)LL2_EDC_L1P_err_str - + derr * (Uint32)LL2_EDC_L1D_err_str - + verr * (Uint32)LL2_EDC_victim_err_str - + dmaerr * (Uint32)LL2_EDC_DMA_err_str); - - printf("address 0x%x caused by %s.\n", - errAddr, - errStr); - - if(0==(gpCGEM_regs->L2EDADDR&CSL_CGEM_L2EDADDR_RAM_MASK)) - { - printf(" Error detected in Way %d of L2 cache\n", - (gpCGEM_regs->L2EDADDR&CSL_CGEM_L2EDADDR_WAY_MASK)>>CSL_CGEM_L2EDADDR_WAY_SHIFT); - } - - printf(" total non-correctable error number= %d, total correctable error number= %d.\n", - gpCGEM_regs->L2EDCNEC, gpCGEM_regs->L2EDCPEC); - - CSL_CGEM_clearL2EDCErrorStatus(derr, perr, dmaerr, verr); - } - else - { - puts(" Enter LL2 EDC handler, but no error flag is set!"); - } -} -/***************************************************************************** - Prototype : L1P_ED_handler - Description : L1P EDC processing - Input : None - Output : None - Return Value : - - History : - 1.Date : 2012/10/28 - Author : Brighton Feng - Modification : Created function - -*****************************************************************************/ -void L1P_ED_handler() -{ - Uint32 errAddr; - Uint8 errRAM; - - /* EDC error during DMA access */ - Uint8 dmaerr; - /* EDC error during program fetch access */ - Uint8 perr; - - /* Read PMC EDC status*/ - CSL_CGEM_getPMCErrorDetectionStatus(&dmaerr, &perr); - - if(perr|dmaerr) - { - CSL_CGEM_getPMCErrorInfo(&errAddr, &errRAM); - - exception_record.status.ext_sts.info.memory.fault_address= errAddr*32; - exception_record.status.ext_sts.info.memory.fault_status.L1PEDSTAT= - gpCGEM_regs->L1PEDSTAT; - - if(errRAM) - printf(" L1P RAM "); - else - printf(" L1P Cache "); - - printf("parity check error caused by "); - - if(perr == 1) - { - printf("program fetch "); - - /*flush wrong code in L1P. Code will be refetched from L2*/ - CACHE_invL1p((void *)NRP, 64, CACHE_WAIT); - } - else if(dmaerr == 1) - { - printf("DMA "); - } - printf("at address 0x%x\n", errAddr*32); - - CSL_CGEM_clearPMCErrorDetectionStatus(dmaerr,perr); - } -} - - -/***************************************************************************** - Prototype : KeyStone_SL2_EDC_handler - Description : SL2 EDC Processing - Input : None - Output : None - Return Value : - - History : - 1.Date : 2012/10/28 - Author : Brighton Feng - Modification : Created function - -*****************************************************************************/ -void KeyStone_SL2_EDC_handler() -{ - /* EDC correctable error during scrubbing cycle */ - Uint8 cses; - /* EDC non-correctable error during scrubbing cycle */ - Uint8 ncses; - /* EDC correctable error during SRAM access*/ - Uint8 cees; - /* EDC non-correctable error during SRAM access*/ - Uint8 ncees; - /* protection fault status*/ - Uint16 pfeStat; - - /* error address */ - Uint32 errAddr, bitPos, PrivID; - - if(gpMSMC_regs->CFGLCKSTAT&CSL_MSMC_CFGLCKSTAT_WSTAT_MASK) - CSL_MSMC_unlockNonMPAX(); - - CSL_MSMC_getPendingInterrupts(&pfeStat, &cees, &ncees, &cses, &ncses); - - exception_record.status.ext_sts.info.memory.fault_status.SMESTAT= - gpMSMC_regs->SMESTAT; - - if((cses == 1)||(ncses == 1)) - { - if(cses == 1) - { - /*scrubbing engine report address offset from 0*/ - errAddr = (gpMSMC_regs->SMCEA&0xFFFFFF)+0xc000000; - exception_record.status.ext_sts.info.memory.fault_address= errAddr; - - bitPos = (gpMSMC_regs->SMCEA&CSL_MSMC_SMCEA_ESYN_MASK) - >>CSL_MSMC_SMCEA_ESYN_SHIFT; - printf("SL2 Correctable error occurred at bit %d of address 0x%x by scrubbing\n", - bitPos, errAddr); - } - if(ncses == 1) - { - /*scrubbing engine report address offset from 0*/ - errAddr = gpMSMC_regs->SMNCEA+0xc000000; - exception_record.status.ext_sts.info.memory.fault_address= errAddr; - - printf("SL2 Non-correctable error occurred at address 0x%x by scrubbing\n", errAddr); - } - printf("%d correctable errors, %d non-correctable errors occurred during scrubbing.\n", - (gpMSMC_regs->SMSECC&CSL_MSMC_SMSECC_SCEC_MASK) - >>CSL_MSMC_SMSECC_SCEC_SHIFT, - (gpMSMC_regs->SMSECC&CSL_MSMC_SMSECC_SNCEC_MASK) - >>CSL_MSMC_SMSECC_SNCEC_SHIFT); - } - if(cees == 1) - { - volatile Uint32 scrubValue; - - errAddr = gpMSMC_regs->SMCERRAR; - exception_record.status.ext_sts.info.memory.fault_address= errAddr; - - //scrub the address to correct the error - scrubValue= *(volatile Uint32 *)errAddr; //touch to cach - *(volatile Uint32 *)errAddr= scrubValue; //make cache dirty - CACHE_wbInvL2((void *)errAddr, 32, CACHE_WAIT); - - bitPos = (gpMSMC_regs->SMCERRXR&CSL_MSMC_SMCERRXR_ESYN_MASK) - >>CSL_MSMC_SMCERRXR_ESYN_SHIFT; - PrivID = (gpMSMC_regs->SMCERRXR&CSL_MSMC_SMCERRXR_SEPID_MASK) - >>CSL_MSMC_SMCERRXR_SEPID_SHIFT; - printf("SL2 Correctable error occurred at bit %d of address 0x%x by PrivID %d ", - bitPos, errAddr, PrivID); - if(gpMSMC_regs->SMCERRXR&CSL_MSMC_SMCERRXR_SER_MASK) - printf("(not from C66x CorePacs)\n"); - else - printf("(from C66x CorePacs)\n"); - } - if(ncees ==1) - { - errAddr = gpMSMC_regs->SMNCERRAR; - exception_record.status.ext_sts.info.memory.fault_address= errAddr; - - PrivID = (gpMSMC_regs->SMNCERRXR&CSL_MSMC_SMNCERRXR_SEPID_MASK) - >>CSL_MSMC_SMNCERRXR_SEPID_SHIFT; - printf("SL2 Non-correctable error occurred at address 0x%x by PrivID %d ", - errAddr, PrivID); - if(gpMSMC_regs->SMNCERRXR&CSL_MSMC_SMNCERRXR_SER_MASK) - printf("(not from C66x CorePacs)\n"); - else - printf("(from C66x CorePacs)\n"); - } - - /* clear EDC error status */ - CSL_MSMC_clearRawInterruptStatus(0, cees,ncees, cses, ncses); - - CSL_MSMC_lockNonMPAX(); -} - -/*===============================Exception=============================*/ -//data structure to save exception info -Exception_Record exception_record; - -/*some exception events routed from CIC to INTC and then to exception moduel, -all these events are routed to one input of INTC*/ -Uint32 guwIntcCICExcEvtIdx= 95; /*INTC event number mapping to CIC exception events*/ -Uint32 gCIC_EXC_out_num = 15; //CIC output event number -Uint32 gCIC_EXC_EN_MASK[8]= {0,0,0,0,0,0,0,0}; -/***************************************************************************** - Prototype : KeyStone_CIC_exception_events_mapping - Description : CIC exception event mapping to the NMI external exception - Input : void - Output : None - Return Value : - - History : - 1.Date : 2012/10/5 - Author : Brighton Feng - Modification : Created function - - 2.Date : 2012/10/20 - Author : Zhan - Modification : Add event for TCI6614 - - 3.Date : 2012/10/28 - Author : Brighton Feng -*****************************************************************************/ -void KeyStone_CIC_exception_events_mapping(void) -{ - TDSP_Board_Type DSP_Board_Type= KeyStone_Get_dsp_board_type(); - -#if 1 - if(C6670_EVM==DSP_Board_Type - ||DUAL_NYQUIST_EVM==DSP_Board_Type - ||TCI6614_EVM==DSP_Board_Type) - { - gCIC_EXC_out_num= 15+16*DNUM; - } - else if(C6678_EVM==DSP_Board_Type) - { - if(DNUM<4) - gCIC_EXC_out_num= 7+8*DNUM; - else - { - gCIC_EXC_out_num= 7+8*(DNUM-4); - gpCIC_regs= gpCIC1_regs; - } - } - else - { - puts("Unknown DSP board type!"); - return; - } -#endif - - /*-----------------------CP_INTC configuration---------------------*/ - /* Disable Global host interrupts. */ - gpCIC_regs->GLOBAL_ENABLE_HINT_REG= 0; - - /* route following system events to CIC out (event 22 of INTC), and then to exception - TCI6614, C6670, C6678: - CIC: 0 EDMA3CC1 EDMACC_ERRINT EDMA3CC1 error interrupt - CIC: 2 EDMA3CC1 EDMATC_ERRINT0 EDMA3CC1 EDMA3TC0 error interrupt - CIC: 3 EDMA3CC1 EDMATC_ERRINT1 EDMA3CC1 EDMA3TC1 error interrupt - CIC: 4 EDMA3CC1 EDMATC_ERRINT2 EDMA3CC1 EDMA3TC2 error interrupt - CIC: 5 EDMA3CC1 EDMATC_ERRINT3 EDMA3CC1 EDMA3TC3 error interrupt - CIC: 16 EDMA3CC2 EDMACC_ERRINT EDMA3CC2 error interrupt - CIC: 18 EDMA3CC2 EDMATC_ERRINT0 EDMA3CC2 EDMA3TC0 error interrupt - CIC: 19 EDMA3CC2 EDMATC_ERRINT1 EDMA3CC2 EDMA3TC1 error interrupt - CIC: 20 EDMA3CC2 EDMATC_ERRINT2 EDMA3CC2 EDMA3TC2 error interrupt - CIC: 21 EDMA3CC2 EDMATC_ERRINT3 EDMA3CC2 EDMA3TC3 error interrupt - CIC: 32 EDMA3CC0 EDMACC_ERRINT EDMA3CC0 error interrupt - CIC: 34 EDMA3CC0 EDMATC_ERRINT0 EDMA3CC0 EDMA3TC0 error interrupt - CIC: 35 EDMA3CC0 EDMATC_ERRINT1 EDMA3CC0 EDMA3TC1 error interrupt - CIC: 99 MSMC_dedc_nc_error Non-correctable soft error detected on SRAM read - CIC: 100 MSMC_scrub_nc_error Non-correctable soft error detected during scrub cycle - CIC: 102 MSMC_mpf_error8 Memory protection fault indicators for each system master PrivID - CIC: 103 MSMC_mpf_error9 Memory protection fault indicators for each system master PrivID - CIC: 104 MSMC_mpf_error10 Memory protection fault indicators for each system master PrivID - CIC: 105 MSMC_mpf_error11 Memory protection fault indicators for each system master PrivID - CIC: 106 MSMC_mpf_error12 Memory protection fault indicators for each system master PrivID - CIC: 107 MSMC_mpf_error13 Memory protection fault indicators for each system master PrivID - CIC: 108 MSMC_mpf_error14 Memory protection fault indicators for each system master PrivID - CIC: 109 MSMC_mpf_error15 Memory protection fault indicators for each system master PrivID - CIC: 110 DDR3_ERR DDR3 ECC Error Interrupt - TCI6614, C6670: - CIC: 170 MSMC_mpf_error4 Memory protection fault indicators for each system master PrivID - CIC: 171 MSMC_mpf_error5 Memory protection fault indicators for each system master PrivID - CIC: 172 MSMC_mpf_error6 Memory protection fault indicators for each system master PrivID - CIC: 173 MSMC_mpf_error7 Memory protection fault indicators for each system master PrivID - */ - KeyStone_CIC_event_map(gpCIC_regs, 0 , gCIC_EXC_out_num); - KeyStone_CIC_event_map(gpCIC_regs, 2 , gCIC_EXC_out_num); - KeyStone_CIC_event_map(gpCIC_regs, 3 , gCIC_EXC_out_num); - KeyStone_CIC_event_map(gpCIC_regs, 4 , gCIC_EXC_out_num); - KeyStone_CIC_event_map(gpCIC_regs, 5 , gCIC_EXC_out_num); - KeyStone_CIC_event_map(gpCIC_regs, 16, gCIC_EXC_out_num); - KeyStone_CIC_event_map(gpCIC_regs, 18, gCIC_EXC_out_num); - KeyStone_CIC_event_map(gpCIC_regs, 19, gCIC_EXC_out_num); - KeyStone_CIC_event_map(gpCIC_regs, 20, gCIC_EXC_out_num); - KeyStone_CIC_event_map(gpCIC_regs, 21, gCIC_EXC_out_num); - gCIC_EXC_EN_MASK[0] |= - (1<<0 ) - |(1<<2 ) - |(1<<3 ) - |(1<<4 ) - |(1<<5 ) - |(1<<16) - |(1<<18) - |(1<<19) - |(1<<20) - |(1<<21); - - KeyStone_CIC_event_map(gpCIC_regs, 32, gCIC_EXC_out_num); - KeyStone_CIC_event_map(gpCIC_regs, 34, gCIC_EXC_out_num); - KeyStone_CIC_event_map(gpCIC_regs, 35, gCIC_EXC_out_num); - gCIC_EXC_EN_MASK[1] |= - (1<<(32-32)) - |(1<<(34-32)) - |(1<<(35-32)); - - KeyStone_CIC_event_map(gpCIC_regs, 99, gCIC_EXC_out_num); - KeyStone_CIC_event_map(gpCIC_regs, 100, gCIC_EXC_out_num); - KeyStone_CIC_event_map(gpCIC_regs, 102, gCIC_EXC_out_num); - KeyStone_CIC_event_map(gpCIC_regs, 103, gCIC_EXC_out_num); - KeyStone_CIC_event_map(gpCIC_regs, 104, gCIC_EXC_out_num); - KeyStone_CIC_event_map(gpCIC_regs, 105, gCIC_EXC_out_num); - KeyStone_CIC_event_map(gpCIC_regs, 106, gCIC_EXC_out_num); - KeyStone_CIC_event_map(gpCIC_regs, 107, gCIC_EXC_out_num); - KeyStone_CIC_event_map(gpCIC_regs, 108, gCIC_EXC_out_num); - KeyStone_CIC_event_map(gpCIC_regs, 109, gCIC_EXC_out_num); - KeyStone_CIC_event_map(gpCIC_regs, 110, gCIC_EXC_out_num); - gCIC_EXC_EN_MASK[3] |= - (1<<(99 -32*3)) - |(1<<(100-32*3)) - |(1<<(102-32*3)) - |(1<<(103-32*3)) - |(1<<(104-32*3)) - |(1<<(105-32*3)) - |(1<<(106-32*3)) - |(1<<(107-32*3)) - |(1<<(108-32*3)) - |(1<<(109-32*3)) - |(1<<(110-32*3)); - - if(C6670_EVM==DSP_Board_Type - ||DUAL_NYQUIST_EVM==DSP_Board_Type - ||TCI6614_EVM==DSP_Board_Type) - { - KeyStone_CIC_event_map(gpCIC_regs, 170, gCIC_EXC_out_num); - KeyStone_CIC_event_map(gpCIC_regs, 171, gCIC_EXC_out_num); - KeyStone_CIC_event_map(gpCIC_regs, 172, gCIC_EXC_out_num); - KeyStone_CIC_event_map(gpCIC_regs, 173, gCIC_EXC_out_num); - gCIC_EXC_EN_MASK[5] |= - (1<<(170-32*5)) - |(1<<(171-32*5)) - |(1<<(172-32*5)) - |(1<<(173-32*5)); - } - - /* ----------- Mapping MPU interrupt for different chips start -----------------------*/ - if(C6670_EVM==DSP_Board_Type - ||DUAL_NYQUIST_EVM==DSP_Board_Type - ||C6678_EVM==DSP_Board_Type) - { - /* route the following system events to CIC out - CIC: 90 MPU0 addressing violation interrupt and protection violation interrupt - CIC: 92 MPU1 addressing violation interrupt and protection violation interrupt - CIC: 94 MPU2 addressing violation interrupt and protection violation interrupt - CIC: 96 MPU3 addressing violation interrupt and protection violation interrupt - */ - KeyStone_CIC_event_map(gpCIC_regs, 90, gCIC_EXC_out_num); - KeyStone_CIC_event_map(gpCIC_regs, 92, gCIC_EXC_out_num); - KeyStone_CIC_event_map(gpCIC_regs, 94, gCIC_EXC_out_num); - KeyStone_CIC_event_map(gpCIC_regs, 96, gCIC_EXC_out_num); - gCIC_EXC_EN_MASK[2] |= - (1<<(90 -32*2)) - |(1<<(92 -32*2)) - |(1<<(94 -32*2)); - gCIC_EXC_EN_MASK[3] |= - (1<<(96 -32*3)); - - /* 6618_6670 only */ - if(C6670_EVM==DSP_Board_Type - ||DUAL_NYQUIST_EVM==DSP_Board_Type) - { - /* - CIC: 174 MPU4 addressing violation interrupt and protection violation interrupt - CIC: 180 MPU5 addressing violation interrupt and protection violation interrupt - */ - KeyStone_CIC_event_map(gpCIC_regs, 174, gCIC_EXC_out_num); - KeyStone_CIC_event_map(gpCIC_regs, 180, gCIC_EXC_out_num); - gCIC_EXC_EN_MASK[5] |= - (1<<(174-32*5)) - |(1<<(180-32*5)); - } - } - - if(TCI6614_EVM==DSP_Board_Type) - { - /* route the following system events to CIC out - CIC: 23 MPU0~7 addressing violation interrupt combine output - CIC: 37 MPU0~7 protection violation interrupt combine output - */ - KeyStone_CIC_event_map(gpCIC_regs, 23, gCIC_EXC_out_num); - KeyStone_CIC_event_map(gpCIC_regs, 37, gCIC_EXC_out_num); - gCIC_EXC_EN_MASK[0] |= - (1<<23); - gCIC_EXC_EN_MASK[1] |= - (1<<(37 -32)); - - } - /* ----------- Mapping MPU interrupt for different chips end -----------------------*/ - - /* Enable Global host interrupts. */ - gpCIC_regs->GLOBAL_ENABLE_HINT_REG= 1; - -} -/***************************************************************************** - Prototype : KeyStone_Exception_cfg - Description : Config the system err and external exception to generate the NMI. - Call this function as last step after all - configuration/initialization complete - Input : Bool bGlobalExceptionMaster. If TRUE, the global exception events - from CIC will be routed to exception model of this CPU core. - Output : None - Return Value : -*****************************************************************************/ -void KeyStone_Exception_cfg(Bool bGlobalExceptionMaster) -{ - - puts("Enable Exception handling..."); - - TSCL = 0; /* Enable the TSC */ - - memset(&exception_record, 0, sizeof(exception_record)); -#if 0 - /*Clear all CPU events*/ - gpCGEM_regs->EVTCLR[0]= 0xFFFFFFFF; - gpCGEM_regs->EVTCLR[1]= 0xFFFFFFFF; - gpCGEM_regs->EVTCLR[2]= 0xFFFFFFFF; - gpCGEM_regs->EVTCLR[3]= 0xFFFFFFFF; -#endif - /*clear memory fault*/ - gpCGEM_regs->L1PMPFCR = 1; - gpCGEM_regs->L1DMPFCR = 1; - gpCGEM_regs->L2MPFCR = 1; - gpXMC_regs->XMPFCR = 1; - - /*clear configuration bus error*/ - gpCGEM_regs->ICFGMPFCR= 1; - gpCGEM_regs->ECFGERRCLR= 1; - - /* clear the MDMAERR */ - gpCGEM_regs->MDMAERRCLR = 1; - - /*clear interrupt drop staus*/ - gpCGEM_regs->INTXCLR = 1; - - gpCGEM_regs->INTDMASK= ~IER; /*only monitor drop of enabled interrupts*/ - - /*enable events: - 10 MSMC_mpf_error_n MSMC Memory protection fault caused by local CorePac - 96 INTERR Dropped CPU interrupt event - 97 EMC_IDMAERR Invalid IDMA parameters - 110 MDMAERREVT XMC VBUSM error event - 113 PMC_ED Single bit error detected during DMA accesses L1P - 117 UMC_ED2 Uncorrected bit error detected LL2 - 119 SYS_CMPA CPU Memory Protection Fault for local configuration of INTC and power control - 120 PMC_CMPA CPU memory protection fault for L1P - 121 PMC_DMPA DMA memory protection fault for L1P - 122 DMC_CMPA CPU memory protection fault for L1D (and other memory read finally goes through the L1D controller) - 123 DMC_DMPA DMA memory protection fault for L1D - 124 UMC_CMPA CPU memory protection fault for LL2 - 125 UMC_DMPA DMA memory protection fault for LL2 - 126 EMC_CMPA CPU memory protection fault for other local configuration space between 0x01000000 - 0x01BFFFFF - 127 EMC_BUSERR Bus Error Interrupt for global configuration space between 0x01C00000 - 0x07FFFFFF - */ - gpCGEM_regs->EXPMASK[0]= ~(1<EXPMASK[1]= 0xFFFFFFFF; - gpCGEM_regs->EXPMASK[2]= 0xFFFFFFFF; - gpCGEM_regs->EXPMASK[3]= ~((1<<(CSL_GEM_INTERR - 96))| - (1<<(CSL_GEM_EMC_IDMAERR-96))| - (1<<(CSL_GEM_MDMAERREVT-96))| - (1<<(CSL_GEM_PMC_ED-96))| - (1<<(CSL_GEM_UMC_ED2-96))| - (1<<(CSL_GEM_SYS_CMPA-96))| - (1<<(CSL_GEM_PMC_CMPA-96))| - (1<<(CSL_GEM_PMC_DMPA-96))| - (1<<(CSL_GEM_DMC_CMPA-96))| - (1<<(CSL_GEM_DMC_DMPA-96))| - (1<<(CSL_GEM_UMC_CMPA-96))| - (1<<(CSL_GEM_UMC_DMPA-96))| - (1<<(CSL_GEM_EMC_CMPA-96))| - (1<<(CSL_GEM_EMC_BUSERR-96))); - - - if(bGlobalExceptionMaster) - { - /*enable exception events routed from CIC, - please note, this should be only configured for one CPU*/ - KeyStone_CIC_exception_events_mapping(); - gpCGEM_regs->EXPMASK[guwIntcCICExcEvtIdx>>5] &= (~(1<<(guwIntcCICExcEvtIdx&0x1F))); - } - - /*clear exception flag*/ - ECR = EFR; - IERR = 0; - - /*Eanble external exception, global exception enable*/ - TSR = TSR| - (1<>CSL_CGEM_MDMAERR_ERR_SHIFT; - if (1==err) { - puts(" MDMA read status error detected"); - } - else if (2==err) { - puts(" MDMA write status error detected"); - } - else if (3==err) { - puts(" CFG read status error detected"); - } - else if (4==err) { - puts(" CFG write status error detected"); - } - - printf(" XID (Transaction ID)= %d\n", - (ERR_REG & CSL_CGEM_MDMAERR_XID_MASK)>>CSL_CGEM_MDMAERR_XID_SHIFT); - - stat= (ERR_REG & CSL_CGEM_MDMAERR_STAT_MASK)>>CSL_CGEM_MDMAERR_STAT_SHIFT; - printf(" %s\n", bus_err_stat_str[stat]); -} - -/***************************************************************************** - Prototype : KeyStone_CIC_EXC_handler - Description : This function handle the exception events from CIC - Input : void - Output : None - Return Value : void - - History : - 1.Date : 2012/10/18 - Author : Zhan - Modification : Created function - - 2.Date : 2012/10/28 - Author : Brighton Feng - Modification : Add EDMA error processing - -*****************************************************************************/ -void KeyStone_CIC_EXC_handler() -{ - int i; - Uint32 status[4], status5 = 0; - - TDSP_Board_Type DSP_Board_Type; - - DSP_Board_Type= KeyStone_Get_dsp_board_type(); - - /*Step1: Disable CIC host interrupt*/ - KeyStone_CIC_disable_host_int(gpCIC_regs, gCIC_EXC_out_num); - - status[0]= gpCIC_regs->ENA_STATUS_REG[0]&gCIC_EXC_EN_MASK[0]; - status[1]= gpCIC_regs->ENA_STATUS_REG[1]&gCIC_EXC_EN_MASK[1]; - status[2]= gpCIC_regs->ENA_STATUS_REG[2]&gCIC_EXC_EN_MASK[2]; - status[3]= gpCIC_regs->ENA_STATUS_REG[3]&gCIC_EXC_EN_MASK[3]; - exception_record.status.ext_sts.CIC_STATUS[0]= status[0]; - exception_record.status.ext_sts.CIC_STATUS[1]= status[1]; - exception_record.status.ext_sts.CIC_STATUS[2]= status[2]; - exception_record.status.ext_sts.CIC_STATUS[3]= status[3]; - - /*Step2: clear system events*/ - gpCIC_regs->ENA_STATUS_REG[0]= status[0]; - gpCIC_regs->ENA_STATUS_REG[1]= status[1]; - gpCIC_regs->ENA_STATUS_REG[2]= status[2]; - gpCIC_regs->ENA_STATUS_REG[3]= status[3]; - - /* The different device INTC number is different, if read the non-exist space will - trigger the L1D memory protection error. - */ - if((C6670_EVM == DSP_Board_Type) - ||(DUAL_NYQUIST_EVM == DSP_Board_Type) - ||(TCI6614_EVM == DSP_Board_Type)) - { - status5 = gpCIC_regs->ENA_STATUS_REG[5]&gCIC_EXC_EN_MASK[5]; - exception_record.status.ext_sts.CIC_STATUS[5]= status5; - - /*Step2: clear system events*/ - gpCIC_regs->ENA_STATUS_REG[5]= status5 ; - } - - /*----------------------------EDMA error-----------------------------*/ - /* - CIC: 0 EDMA3CC1 EDMACC_ERRINT EDMA3CC1 error interrupt - CIC: 2 EDMA3CC1 EDMATC_ERRINT0 EDMA3CC1 EDMA3TC0 error interrupt - CIC: 3 EDMA3CC1 EDMATC_ERRINT1 EDMA3CC1 EDMA3TC1 error interrupt - CIC: 4 EDMA3CC1 EDMATC_ERRINT2 EDMA3CC1 EDMA3TC2 error interrupt - CIC: 5 EDMA3CC1 EDMATC_ERRINT3 EDMA3CC1 EDMA3TC3 error interrupt*/ - if(status[0]&0x3D) - EDMA_error_handler(1, status[0]&0x3D); - - /* - CIC: 16 EDMA3CC2 EDMACC_ERRINT EDMA3CC2 error interrupt - CIC: 18 EDMA3CC2 EDMATC_ERRINT0 EDMA3CC2 EDMA3TC0 error interrupt - CIC: 19 EDMA3CC2 EDMATC_ERRINT1 EDMA3CC2 EDMA3TC1 error interrupt - CIC: 20 EDMA3CC2 EDMATC_ERRINT2 EDMA3CC2 EDMA3TC2 error interrupt - CIC: 21 EDMA3CC2 EDMATC_ERRINT3 EDMA3CC2 EDMA3TC3 error interrupt*/ - if((status[0]>>16)&0x3D) - EDMA_error_handler(2, (status[0]>>16)&0x3D); - - /* - CIC: 32 EDMA3CC0 EDMACC_ERRINT EDMA3CC0 error interrupt - CIC: 34 EDMA3CC0 EDMATC_ERRINT0 EDMA3CC0 EDMA3TC0 error interrupt - CIC: 35 EDMA3CC0 EDMATC_ERRINT1 EDMA3CC0 EDMA3TC1 error interrupt*/ - if(status[1]&0xD) - EDMA_error_handler(0, status[1]&0xD); - - /*----------------------------MPU error-----------------------------*/ - if(TCI6614_EVM == DSP_Board_Type) - { - //CIC: 23 MPU0~7 addressing violation interrupt combine output - //CIC: 37 MPU0~7 protection violation interrupt combine output - if((status[0]&(1<<23))||(status[1]&(1<<(37-32)))) - { - for(i=0; i<8; i++) - { - /*MPU5 (for BCP) of TCI6614 is only accessible - when BCP is enabled through PSC*/ - if((5==i)&& - ((CSL_PSC_getPowerDomainState(5) != PSC_PDSTATE_ON) || - (CSL_PSC_getModuleState (12) != PSC_MODSTATE_ENABLE))) - continue; - - if(gpMPU_regs[i]->INT_RAW_STATUS_SET & 0x3) - { - KeyStone_peripherals_MPU_excepiton_handler(i); - } - } - - /*The MPU events in TCI6614 are different from other KeyStone - devices. All the MPU0~7 events are combined into single event - and connected to the CIC0 as one system event. - We have to clear the MPU event flag at the source level first - and then are able to clear the CIC flags because the INTD for the - MPU events is for the combination purpose but do not convert - the level interrupt to pulse.*/ - /*clear system events*/ - gpCIC_regs->ENA_STATUS_REG[0]= status[0]; - gpCIC_regs->ENA_STATUS_REG[1]= status[1]; - } - } - else - { - //CIC: 90 MPU0 addressing violation interrupt and protection violation interrupt - if(status[2]&(1<<(90-64))) - { - KeyStone_peripherals_MPU_excepiton_handler(0); - } - //CIC: 92 MPU1 addressing violation interrupt and protection violation interrupt - if(status[2]&(1<<(92-64))) - { - KeyStone_peripherals_MPU_excepiton_handler(1); - } - //CIC: 94 MPU2 addressing violation interrupt and protection violation interrupt - if(status[2]&(1<<(94-64))) - { - KeyStone_peripherals_MPU_excepiton_handler(2); - } - //CIC: 96 MPU3 addressing violation interrupt and protection violation interrupt - if(status[3]&(1<<(96-96))) - { - KeyStone_peripherals_MPU_excepiton_handler(3); - } - - if((C6670_EVM == DSP_Board_Type) - ||(DUAL_NYQUIST_EVM == DSP_Board_Type)) - { - //CIC: 174 MPU4 addressing violation interrupt and protection violation interrupt - //CIC: 180 MPU5 addressing violation interrupt and protection violation interrupt - if(status5&(1<<(174-160))) - { - KeyStone_peripherals_MPU_excepiton_handler(4); - } - if(status5&(1<<(180-160))) - { - KeyStone_peripherals_MPU_excepiton_handler(5); - } - } - } - - /*----------------------------MSMC error-----------------------------*/ - //CIC: 99 MSMC_dedc_nc_error Non-correctable (2-bit) soft error detected on SRAM read - if(status[3]&(1<<(99-96))) - { - KeyStone_SL2_EDC_handler(); - } - //CIC: 100 MSMC_scrub_nc_error Non-correctable (2-bit) soft error detected during scrub cycle - if(status[3]&(1<<(100-96))) - { - KeyStone_SL2_EDC_handler(); - } - - /* - CIC: 102 MSMC_mpf_error8 Memory protection fault indicators for each system master PrivID - CIC: 103 MSMC_mpf_error9 Memory protection fault indicators for each system master PrivID - CIC: 104 MSMC_mpf_error10 Memory protection fault indicators for each system master PrivID - CIC: 105 MSMC_mpf_error11 Memory protection fault indicators for each system master PrivID - CIC: 106 MSMC_mpf_error12 Memory protection fault indicators for each system master PrivID - CIC: 107 MSMC_mpf_error13 Memory protection fault indicators for each system master PrivID - CIC: 108 MSMC_mpf_error14 Memory protection fault indicators for each system master PrivID - CIC: 109 MSMC_mpf_error15 Memory protection fault indicators for each system master PrivID*/ - if((status[3]>>(102-96))&0xFF) - KeyStone_MSMC_protection_exception_handler(); - - if((C6670_EVM == DSP_Board_Type) - ||(DUAL_NYQUIST_EVM == DSP_Board_Type) - ||(TCI6614_EVM == DSP_Board_Type)) - { - /* - CIC: 170 MSMC_mpf_error4 Memory protection fault indicators for each system master PrivID - CIC: 171 MSMC_mpf_error5 Memory protection fault indicators for each system master PrivID - CIC: 172 MSMC_mpf_error6 Memory protection fault indicators for each system master PrivID - CIC: 173 MSMC_mpf_error7 Memory protection fault indicators for each system master PrivID*/ - if((status5>>(170-160))&0xF) - KeyStone_MSMC_protection_exception_handler(); - - } - - /*----------------------------DDR ECC error-------------------------*/ - //CIC: 110 DDR3_ERR DDR3_EMIF Error Interrupt - if(status[3]&(1<<(110-96))) - { - printf(" DDR ECC error happened during "); - - exception_record.status.ext_sts.info.memory.fault_status.DDR_IRQSTATUS_SYS= - gpDDR_regs->IRQSTATUS_SYS; - - if(gpDDR_regs->IRQSTATUS_SYS&CSL_EMIF4F_IRQSTATUS_SYS_REG_RD_ECC_ERR_SYS_MASK) - printf("read "); - if(gpDDR_regs->IRQSTATUS_SYS&CSL_EMIF4F_IRQSTATUS_SYS_REG_WR_ECC_ERR_SYS_MASK) - printf("write "); - printf(".\n"); - - //clear the status - gpDDR_regs->IRQSTATUS_SYS= CSL_EMIF4F_IRQSTATUS_SYS_REG_RD_ECC_ERR_SYS_MASK - |CSL_EMIF4F_IRQSTATUS_SYS_REG_WR_ECC_ERR_SYS_MASK; - } - - /*Step3: Enable the CIC host interrupt */ - KeyStone_CIC_enable_host_int(gpCIC_regs, gCIC_EXC_out_num); - -} - -/***************************************************************************** - Prototype : KeyStone_EXC_external - Description : external exception processing - Input : void - Output : None - Return Value : - - History : - 1.Date : 2010/12/12 - Author : Brighton Feng - Modification : Created function -*****************************************************************************/ -void KeyStone_EXC_external(void) -{ - int i; - unsigned int INTXSTAT, flag[4]; - - for(i= 0; i<4; i++) - { - flag[i] = gpCGEM_regs->MEXPFLAG[i]; - if(flag[i]) - { - exception_record.status.ext_sts.MEXPFLAG[i]= flag[i]; - printf("External exception happened. MEXPFLAG[%d]=0x%x.\n", - i, flag[i]); - gpCGEM_regs->EVTCLR[i] = flag[i]; - } - } - - if(0 == (flag[0]|flag[1]|flag[2]|flag[3])) - { - puts("Enter external Exception service routine, but external excpetion flage is 0!"); - return; - } - - /*Exception events routed from CIC*/ - if(flag[guwIntcCICExcEvtIdx>>5] & (1<<(guwIntcCICExcEvtIdx&0x1F))) - { - KeyStone_CIC_EXC_handler(); - } - - /*MSMC memory protection exception*/ - if(flag[0]&(1<INTXSTAT; - exception_record.status.ext_sts.info.INTXSTAT= INTXSTAT; - - if(INTXSTAT&CSL_CGEM_INTXSTAT_DROP_MASK) - printf(" Event 96: DSP Interrupt %d (INTC input Event %d) dropped\n", - (INTXSTAT&CSL_CGEM_INTXSTAT_CPUINT_MASK)>>CSL_CGEM_INTXSTAT_CPUINT_SHIFT, - (INTXSTAT&CSL_CGEM_INTXSTAT_SYSINT_MASK)>>CSL_CGEM_INTXSTAT_SYSINT_SHIFT); - } - - if(flag[3]&(1<<(CSL_GEM_EMC_IDMAERR-96))) - puts(" Event 97: EMC_IDMAERR Invalid IDMA parameters"); - - /*MDMA XMC VBUSM error*/ - if(flag[3]&(1<<(CSL_GEM_MDMAERREVT-96))) - { - puts(" Event 110: MDMAERREVT XMC VBUSM error event"); - if(gpXMC_regs->XMPFSR) - { - /*XMC protection error*/ - memory_protection_exception_handler(gpXMC_regs->XMPFAR, gpXMC_regs->XMPFSR); - gpXMC_regs->XMPFCR = 1; - } - else - { - /*other VBUSM error*/ - Bus_error_handler(gpCGEM_regs->MDMAERR); - } - /* clear the MDMAERR */ - gpCGEM_regs->MDMAERRCLR = 1; - } - - /*L1P Single bit error detected during DMA read*/ - if(flag[3]&(1<<(CSL_GEM_PMC_ED-96))) - { - puts(" Event 113: PMC_ED Single bit error detected during DMA read"); - L1P_ED_handler(); - } - - /*LL2 Uncorrected bit error detected*/ - if(flag[3]&(1<<(CSL_GEM_UMC_ED2-96))) - { - puts(" Event 117: UMC_ED2 Uncorrected bit error detected"); - LL2_EDC_handler(FALSE); - } - - /*local register memory protection exception*/ - if(flag[3]&(1<<(CSL_GEM_SYS_CMPA-96))) - { - puts(" Event 119: SYS_CMPA CPU Memory Protection Fault for local configuration of INTC and power control"); - } - - /*L1P memory protection exception*/ - if(flag[3]&(3<<(CSL_GEM_PMC_CMPA-96))) - { - if(flag[3]&(1<<(CSL_GEM_PMC_CMPA-96))) - puts(" Event 120: PMC_CMPA CPU memory protection fault for L1P"); - if(flag[3]&(1<<(CSL_GEM_PMC_DMPA-96))) - puts(" Event 121: PMC_DMPA DMA memory protection fault for L1P"); - memory_protection_exception_handler(gpCGEM_regs->L1PMPFAR, gpCGEM_regs->L1PMPFSR); - gpCGEM_regs->L1PMPFCR = 1; - } - - /*L1D memory protection exception*/ - if(flag[3]&(3<<(CSL_GEM_DMC_CMPA-96))) - { - if(flag[3]&(1<<(CSL_GEM_DMC_CMPA-96))) - puts(" Event 122: DMC_CMPA CPU memory protection fault for L1D (and other memory read finally goes through the L1D controller)"); - if(flag[3]&(1<<(CSL_GEM_DMC_DMPA-96))) - puts(" Event 123: DMC_DMPA DMA memory protection fault for L1D"); - memory_protection_exception_handler(gpCGEM_regs->L1DMPFAR, gpCGEM_regs->L1DMPFSR); - gpCGEM_regs->L1DMPFCR = 1; - } - - /*LL2 memory protection exception*/ - if(flag[3]&(3<<(CSL_GEM_UMC_CMPA-96))) - { - if(flag[3]&(1<<(CSL_GEM_UMC_CMPA-96))) - puts(" Event 124: UMC_CMPA CPU memory protection fault for L2 "); - if(flag[3]&(1<<(CSL_GEM_UMC_DMPA-96))) - puts(" Event 125: UMC_DMPA DMA memory protection fault for L2 "); - memory_protection_exception_handler(gpCGEM_regs->L2MPFAR, gpCGEM_regs->L2MPFSR); - gpCGEM_regs->L2MPFCR = 1; - } - - /*local registers protection exception*/ - if(flag[3]&(1<<(CSL_GEM_EMC_CMPA-96))) - { - puts(" Event 126: EMC_CMPA CPU memory protection fault for local configuration space between 0x01000000-0x01BFFFFF"); - memory_protection_exception_handler(gpCGEM_regs->ICFGMPFAR, gpCGEM_regs->ICFGMPFSR); - gpCGEM_regs->ICFGMPFCR= 1; - } - - /*external configuration bus error*/ - if(flag[3]&(Uint32)(1<<(CSL_GEM_EMC_BUSERR-96))) - { - puts(" Event 127: EMC_BUSERR Bus Error Interrupt for global configuration space between 0x01C00000 - 0x07FFFFFF"); - Bus_error_handler(gpCGEM_regs->ECFGERR); - gpCGEM_regs->ECFGERRCLR= 1; - } -} - -char * internal_exception_str[]= -{ - "Instruction fetch exception", - "Fetch packet exception", - "Execute packet exception", - "Opcode exception", - "Resource conflict exception", - "Resource access exception", - "Privilege exception", - "SPLOOP buffer exception", - "Missed stall exception" -}; - -/***************************************************************************** - Prototype : EXC_internal - Description : internal exception handler - Input : void - Output : None - Return Value : - - History : - 1.Date : 2010/12/12 - Author : Brighton Feng - Modification : Created function - -*****************************************************************************/ -/*internal exception handler*/ -void EXC_internal(void) -{ - int i; - unsigned int ierr; - - /*record IERR */ - ierr = IERR; - exception_record.status.IERR= ierr; - - if(ierr) - { - /*Clear internal excpeiton flag*/ - IERR= 0; - - printf("internal excpetion happened. IERR=0x%x.\n", ierr); - for(i=0; i<9; i++) - { - if((ierr>>i)&1) - printf(" %s\n", internal_exception_str[i]); - } - if (ierr & CSL_CHIP_IERR_IFX_MASK) { - /* L1P EDC Processing*/ - L1P_ED_handler(); - } - } - else - puts("Enter Internal Exception service routine, but internal excpetion flage is 0!"); - -} -/***************************************************************************** - Prototype : EXC_nmi - Description : NMI processing - Input : void - Output : None - Return Value : - - History : - 1.Date : 2010/12/12 - Author : Brighton Feng - Modification : Created function - -*****************************************************************************/ -void EXC_NMI(void) -{ - puts("NMI exception happened, normally you should reset the DSP to recover from the problem!"); -} - -/***************************************************************************** - Prototype : EXC_swgen - Description : software generated exception handler - Input : void - Output : None - Return Value : -*****************************************************************************/ -void EXC_swgen(void) -{ - puts("Software generated exception happened."); -} - -/***************************************************************************** - Prototype : Exception_service_routine - Description : Exception service routine - Input : void - Output : None - Return Value : - - History : - 1.Date : 2010/12/12 - Author : Brighton Feng - Modification : Created function - -*****************************************************************************/ -#pragma NMI_INTERRUPT( Exception_service_routine ); -void Exception_service_routine(void) -{ - unsigned int efr, nrp, ntsr, tscl, tsch, irp, itsr; - - /*record timestamp*/ - tscl = TSCL; - exception_record.TSCL= tscl; - tsch = TSCH; - exception_record.TSCH= tsch; - - nrp = NRP; /*record NRP */ - exception_record.NRP= nrp; - ntsr = NTSR; /*record NTSR */ - exception_record.NTSR= ntsr; - efr = EFR; /*record EFR */ - exception_record.EFR= efr; - - irp = IRP; /*record IRP */ - itsr = ITSR; /*record ITSR */ - exception_record.IRP= irp; - exception_record.ITSR= itsr; - - if(efr) - { - /*Clear excpeiton flag*/ - ECR = efr; - - /*check all possible exceptions*/ - if (efr & CSL_CHIP_EFR_OXF_MASK) { - /* S/W generated exception */ - EXC_swgen(); - } - if (efr & CSL_CHIP_EFR_IXF_MASK) { - /* internal exception */ - EXC_internal(); - } - if (efr & CSL_CHIP_EFR_EXF_MASK) { - /* external exception */ - KeyStone_EXC_external(); - } - if (efr & CSL_CHIP_EFR_NXF_MASK) { - /* legacy NMI exception */ - EXC_NMI(); - } - } - else - puts("Enter Exception service routine, but excpetion flage is 0!"); - - printf("NRP=0x%x, NTSR=0x%x, IRP=0x%x, ITSR=0x%x, TSCH= 0x%x, TSCL= 0x%x\n", - nrp, ntsr, irp, itsr, tsch, tscl); - - printf(" B3=0x%x, A4=0x%x, B4= 0x%x, B14= 0x%x, B15= 0x%x\n", - exception_record.B3, exception_record.A4, - exception_record.B4, exception_record.B14, - exception_record.B15); - - /* - It is not always possible to safely exit the exception handling routine. Conditions that - can prevent a safe return from exceptions include: - 1. SPLOOPs that are terminated by an exception cannot be resumed correctly. The - SPLX bit in NTSR should be verified to be 0 before returning. - 2. Exceptions that occur when interrupts are blocked cannot be resumed correctly. - The IB bit in NTSR should be verified to be 0 before returning. - 3. Exceptions that occur at any point in the code that cannot be interrupted safely - (for example, a tight loop containing multiple assignments) cannot be safely - returned to. The compiler will normally disable interrupts at these points in the - program; check the GIE bit in NTSR to be 1 to verify that this condition is met. - 4. NRP is not in valid address space*/ - if((ntsr&CSL_CHIP_TSR_SPLX_MASK) - ||(ntsr&CSL_CHIP_TSR_IB_MASK) - ||(0==(ntsr&CSL_CHIP_TSR_GIE_MASK)) - ||(0x800000>NRP)) - { - puts("Exception happened at a place can not safely return!"); - //while(1); //trap - exit(0); - } - -} - -/***************************************************************************** - Prototype : Nested_Exception_service_routine - Description : Nested Exception service routine - When a non-maskable exception happens in the first exception service routine, - then the reset vector is used when redirecting program execution to service the second - exception. In this case, NTSR and NRP are left unchanged. TSR is copied to ITSR and - the current PC is copied to IRP. TSR is set to the default exception processing value and - the NMIE bit in IER is cleared in this case preventing any further external exceptions. - Input : void - Output : None - Return Value : - - History : - 1.Date : 2010/12/29 - Author : Brighton Feng - Modification : Created function - -*****************************************************************************/ -interrupt void Nested_Exception_service_routine(void) -{ - unsigned int tscl, tsch; - - /*record timestamp*/ - tscl = TSCL; - tsch = TSCH; - - if(0==exception_record.TSCL) - exception_record.TSCL= tscl; - if(0==exception_record.TSCH) - exception_record.TSCH= tsch; - if(0==exception_record.NRP) - exception_record.NRP= NRP; - if(0==exception_record.NTSR) - exception_record.NTSR= NTSR; - if(0==exception_record.EFR) - exception_record.EFR= EFR; - if(0==exception_record.status.IERR) - exception_record.status.IERR= IERR; - - exception_record.IRP= IRP; - exception_record.ITSR= ITSR; - - printf("Nested exception happened! IRP=0x%x, ITSR=0x%x\n", - IRP, ITSR); - - printf("NRP=0x%x, NTSR=0x%x, EFR=0x%x, IERR=0x%x, TSCH= 0x%x, TSCL= 0x%x\n", - NRP, NTSR, EFR, IERR, tsch, tscl); - - while(1); //trap -// exit(0); -} - -/*=========================other utility functions==========================*/ -/*clear all interrupt flag/status, setup ISTP to begining of LL2*/ -void CPU_interrupt_init() -{ - //clear interrupt and excpetion events - ICR = IFR; - ECR = EFR; - IER= 3; //disable all interrupts - - /* disable event combine */ - gpCGEM_regs->EVTMASK[0] = 0xffffffff; - gpCGEM_regs->EVTMASK[1] = 0xffffffff; - gpCGEM_regs->EVTMASK[2] = 0xffffffff; - gpCGEM_regs->EVTMASK[3] = 0xffffffff; - - /*Clear all CPU events*/ - gpCGEM_regs->EVTCLR[0]= 0xFFFFFFFF; - gpCGEM_regs->EVTCLR[1]= 0xFFFFFFFF; - gpCGEM_regs->EVTCLR[2]= 0xFFFFFFFF; - gpCGEM_regs->EVTCLR[3]= 0xFFFFFFFF; - - /*Interrupt Service Table Pointer to begining of LL2 memory*/ - ISTP= 0x800000; -} - -/*enable interrupt to CPU: IER |= uiIER_en_mask; GIE=1*/ -void CPU_interrupt_enable(Uint32 uiIER_en_mask) -{ - ICR= uiIER_en_mask; - IER |= uiIER_en_mask; - - //enable GIE - //TSR = TSR|1; -} - -/***************************************************************************** - Prototype : KeyStone_get_device_info - Description : Get device information - Input : None - Output : None - Return Value : - - History : - 1.Date : 2010/12/12 - Author : Brighton Feng - Modification : Created function - 2.Date : 2014/12/2 - Author : Brighton Feng - Modification : Update to parser device type, boot mode, endian information, - speed grade, required CVDD - -*****************************************************************************/ -//get device speed grade from the EFUSE register -void KeyStone_get_device_speed_grade() -{ - Uint32 uiDevSpeed, uiSpeedCode; - - uiSpeedCode= (DEVSPEED&DEVSPEED_DSP_SPEED_MASK)>>DEVSPEED_DSP_SPEED_SHIFT; - - if(uiSpeedCode&DEVSPEED_800_MHZ_MASK_H) uiDevSpeed= 800; - else if(uiSpeedCode&DEVSPEED_1000_MHZ_MASK_H) uiDevSpeed= 1000; - else if(uiSpeedCode&DEVSPEED_1200_MHZ_MASK_H) uiDevSpeed= 1200; - else if(uiSpeedCode&DEVSPEED_1250_MHZ_MASK_H) uiDevSpeed= 1250; - else if(uiSpeedCode&DEVSPEED_1400_MHZ_MASK_H) uiDevSpeed= 1400; - else if(uiSpeedCode&DEVSPEED_1400_MHZ_MASK_L) uiDevSpeed= 1400; - else if(uiSpeedCode&DEVSPEED_1250_MHZ_MASK_L) uiDevSpeed= 1250; - else if(uiSpeedCode&DEVSPEED_1200_MHZ_MASK_L) uiDevSpeed= 1200; - else if(uiSpeedCode&DEVSPEED_1000_MHZ_MASK_L) uiDevSpeed= 1000; - else uiDevSpeed= 800; - - printf("Device speed grade = %dMHz.\n", uiDevSpeed); -} - -char * device_type_str[]= -{ - "TCI6616", - "C6670/TCI6618", - "C6678/TCI6608", - "TCI6614", - "unknown" -}; -char * endian_str[]= -{ - "big", - "little" -}; -char * boot_mode_str[]= -{ - "No boot or EMIF16(NOR FLASH) or UART", - "Serial Rapid I/O", - "Ethernet (SGMII)", - "Ethernet (SGMII) or NAND FLASH", - "PCIE", - "I2C", - "SPI", - "HyperLink" - }; -char * input_clk_str[]= -{ - "50MHz", - "66.67MHz", - "80MHz", - "100MHz", - "156.25MHz", - "250MHz", - "312.5MHz", - "122.88MHz", - "bypassed" -}; -void KeyStone_get_device_info() -{ - char * boot_mode; - Uint8 ucBootMode, ucBootMaster; - Uint32 uiVID; - Uint8 ucPLL_cfg= 8; //8 means bypassed - Uint32 * DieID= (Uint32 *)&gpBootCfgRegs->DIE_ID_REG0; - Uint32 uiJTAG_ID = gpBootCfgRegs->DEVICE_ID_REG0; - Uint32 uiDevStat = gpBootCfgRegs->BOOT_REG0; - - gDSP_board_type=KeyStone_Get_dsp_board_type(); - - ucBootMode= (uiDevStat&DEVSTAT_BOOTMODE_MASK)>>DEVSTAT_BOOTMODE_SHIFT; - ucBootMaster= (uiDevStat&DEVSTAT_BOOTMASTER_MASK)>>DEVSTAT_BOOTMASTER_SHIFT; - - if((TCI6614_EVM==gDSP_board_type)&&(1==ucBootMaster)) - { - boot_mode= "ARM"; //ARM boot - } - else - boot_mode= boot_mode_str[ucBootMode]; - - //PLL is not configured with SPI and I2C master boot mode - if((5!=ucBootMode)&&(6!=ucBootMode)) - ucPLL_cfg= (uiDevStat&DEVSTAT_SYSPLL_MASK)>>DEVSTAT_SYSPLL_SHIFT; - - printf("JTAG ID= 0x%08x. This is %s device, version variant = %d.\n", uiJTAG_ID, - device_type_str[gDSP_board_type], uiJTAG_ID>>28); - - printf("DEVSTAT= 0x%08x. %s endian, %s boot, PLL configuration implies the input clock for core is %s.\n", - uiDevStat, endian_str[uiDevStat&DEVSTAT_LENDIAN_MASK], boot_mode, - input_clk_str[ucPLL_cfg]); - - uiVID= (gpPSC_regs->VCNTLID&CSL_PSC_VCNTLID_VCNTL_MASK)>>CSL_PSC_VCNTLID_VCNTL_SHIFT; - printf("SmartReflex VID= %d, required core voltage= %.3fV.\n", uiVID, 0.7+(float)uiVID*0.41/64.f); - - printf("Die ID= 0x%08x, 0x%08x, 0x%08x, 0x%08x\n", DieID[0], DieID[1], DieID[2], DieID[3]); - - KeyStone_get_device_speed_grade(); -} -/***************************************************************************** - Prototype : KeyStone_common_device_init - Description : common initialization for internal modules in K2 device - enable memory protection interrupts, EDC for MSMC RAM - History : - 1.Date : July 11, 2014 - Author : Brighton Feng - Modification : Created function -*****************************************************************************/ -void KeyStone_common_device_init() -{ - int i; - KeyStone_get_device_info(); - - /* enable common MPU interrupts */ - for(i=0; i<4; i++) - { - KeyStone_MPU_interrupt_enable(i); - } - - /*Enable MSMC EDC and setup scrubbing cycle counter= 255*1024*/ - KeyStone_SL2_EDC_enable(255); -} - -/***************************************************************************** - Prototype : KeyStone_common_CPU_init - Description : common initialization for internal modules in K2 device - enable TSC, EDC for local RAM; clear cache; protect L1 as cache - History : - 1.Date : September 1, 2014 - Author : Brighton Feng - Modification : Created function -*****************************************************************************/ -void KeyStone_common_CPU_init() -{ - TSC_init(); //initialize TSC to measure cycle - - /*clear all interrupt flag/status, setup ISTP to begining of LL2*/ - CPU_interrupt_init(); - - /*clean cache from previous run, not required from power on or cold reset*/ - CACHE_wbInvAllL2(CACHE_WAIT); - CSL_XMC_invalidatePrefetchBuffer(); - _mfence(); - _mfence(); - - /* protect L1 as cache */ - L1_cache_protection(); - - //Enable MSMC Memory protection error interrupt for local core, refer to MSMC user guide section3.8 - // KeyStone_MSMC_MP_interrupt_en(1< -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/*----------------------PLL registers definition----------------*/ -#define PLLCTL0_PLLD_SHIFT (0) -#define PLLCTL0_PLLD_MASK (0x3F<>4) | 0x80000000) - -/*max number in two numbers*/ -#define MAX(a, b) (a>b?a:b) -/*min number in two numbers*/ -#define MIN(a, b) (a0xFFFF*4) - byteCnt= 0xFFFF*4; - if((Uint32)blockPtr>=0x0C000000&&(Uint32)blockPtr<0x0D000000) //SL2 - { - CACHE_invL1d((void *)blockPtr, byteCnt, CACHE_WAIT); - CSL_XMC_invalidatePrefetchBuffer(); - } - else if((Uint32)blockPtr>=0x10000000) //DDR or other cores - { - CACHE_invL2((void *)blockPtr, byteCnt, CACHE_WAIT); - CSL_XMC_invalidatePrefetchBuffer(); - } - _mfence(); - _mfence(); - -#if CACHE_DISABLE_INT -/*workaround for the "L2 Cache Corruption During Block and Global Coherence Operations -Issue" described in errata of some devices*/ - asm(" nop 8"); - asm(" nop 8"); - _restore_interrupts(uiOldGIE); //restore interrupt -#endif -} - -static inline void WritebackCache(void * blockPtr, Uint32 byteCnt) -{ - if(byteCnt>0xFFFF*4) - byteCnt= 0xFFFF*4; - if((Uint32)blockPtr>=0x0C000000&&(Uint32)blockPtr<0x0D000000) //SL2 - { - CACHE_wbL1d((void *)blockPtr, byteCnt, CACHE_WAIT); - } - else if((Uint32)blockPtr>=0x10000000) //DDR or other cores - { - CACHE_wbL2((void *)blockPtr, byteCnt, CACHE_WAIT); - } - _mfence(); - _mfence(); -} - -static inline void WritebackAllCache(void * blockPtr) -{ - if((Uint32)blockPtr>=0x0C000000&&(Uint32)blockPtr<0x0D000000) //SL2 - { - CACHE_wbAllL1d(CACHE_WAIT);; - } - else if((Uint32)blockPtr>=0x10000000) //DDR or other cores - { - CACHE_wbAllL2(CACHE_WAIT); - } - _mfence(); - _mfence(); -} - -static inline void WritebackInvalidCache(void * blockPtr, Uint32 byteCnt) -{ -#if CACHE_DISABLE_INT -/*workaround for the "L2 Cache Corruption During Block and Global Coherence Operations -Issue" described in errata of some devices*/ - Uint32 uiOldGIE= _disable_interrupts(); -#endif - - if(byteCnt>0xFFFF*4) - byteCnt= 0xFFFF*4; - if((Uint32)blockPtr>=0x0C000000&&(Uint32)blockPtr<0x0D000000) //SL2 - { - CACHE_wbInvL1d((void *)blockPtr, byteCnt, CACHE_WAIT); - CSL_XMC_invalidatePrefetchBuffer(); - } - else if((Uint32)blockPtr>=0x10000000) //DDR or other cores - { - CACHE_wbInvL2((void *)blockPtr, byteCnt, CACHE_WAIT); - CSL_XMC_invalidatePrefetchBuffer(); - } - _mfence(); - _mfence(); - -#if CACHE_DISABLE_INT -/*workaround for the "L2 Cache Corruption During Block and Global Coherence Operations -Issue" described in errata of some devices*/ - asm(" nop 8"); - asm(" nop 8"); - _restore_interrupts(uiOldGIE); //restore interrupt -#endif -} - -static inline void WritebackInvalidAllCache(void * blockPtr) -{ -#if CACHE_DISABLE_INT -/*workaround for the "L2 Cache Corruption During Block and Global Coherence Operations -Issue" described in errata of some devices*/ - Uint32 uiOldGIE= _disable_interrupts(); -#endif - - if((Uint32)blockPtr>=0x0C000000&&(Uint32)blockPtr<0x0D000000) //SL2 - { - CACHE_wbInvAllL1d(CACHE_WAIT);//CACHE_invL1d((void *)blockPtr, byteCnt, CACHE_WAIT); - CSL_XMC_invalidatePrefetchBuffer(); - } - else if((Uint32)blockPtr>=0x10000000) //DDR or other cores - { - //CACHE_invL2((void *)blockPtr, byteCnt, CACHE_WAIT); - CACHE_wbInvAllL2(CACHE_WAIT); - CSL_XMC_invalidatePrefetchBuffer(); - } - _mfence(); - _mfence(); - -#if CACHE_DISABLE_INT -/*workaround for the "L2 Cache Corruption During Block and Global Coherence Operations -Issue" described in errata of some devices*/ - asm(" nop 8"); - asm(" nop 8"); - _restore_interrupts(uiOldGIE); //restore interrupt -#endif -} - -static inline unsigned int SWAP_ENDIAN(unsigned int byte_index) -{ -#ifdef _BIG_ENDIAN - return ((byte_index&0xFFFFFFFC)+(3-byte_index&3)); -#else - return byte_index; -#endif -} - -static inline void KeyStone_CIC_clear_system_event(CSL_CPINTCRegs* cpIntcRegs, - int input_event_num) -{ - volatile Uint32 dummy_value; - - /*clear input interrupts events*/ - cpIntcRegs->STATUS_CLR_INDEX_REG= input_event_num; - - /*dummy read to make sure the previous write data land into the register*/ - dummy_value= cpIntcRegs->STATUS_CLR_INDEX_REG; -} - -static inline void KeyStone_CIC_disable_host_int(CSL_CPINTCRegs* cpIntcRegs, - int host_int_num) -{ - volatile Uint32 dummy_value; - - /* Disable the host interrupt */ - cpIntcRegs->HINT_ENABLE_CLR_INDEX_REG = host_int_num; - - /*dummy read to make sure the previous write data land into the register*/ - dummy_value= cpIntcRegs->HINT_ENABLE_CLR_INDEX_REG; -} - -static inline void KeyStone_CIC_enable_host_int(CSL_CPINTCRegs* cpIntcRegs, - int host_int_num) -{ - volatile Uint32 dummy_value; - - /* Enable the host interrupt */ - cpIntcRegs->HINT_ENABLE_SET_INDEX_REG = host_int_num; - - /*dummy read to make sure the previous write data land into the register*/ - dummy_value= cpIntcRegs->HINT_ENABLE_SET_INDEX_REG; -} - -static inline void KeyStone_CIC_event_map(CSL_CPINTCRegs* cpIntcRegs, - int input_event_num, int out_num) -{ - /*Map input event to output*/ - cpIntcRegs->CH_MAP[SWAP_ENDIAN(input_event_num)]= out_num; - - /*clear input interrupts events*/ - cpIntcRegs->STATUS_CLR_INDEX_REG= input_event_num; - - /*enable input interrupts events*/ - cpIntcRegs->ENABLE_SET_INDEX_REG= input_event_num; - - /*enable output*/ - cpIntcRegs->HINT_ENABLE_SET_INDEX_REG= out_num; -} - - -typedef enum -{ - DUAL_NYQUIST_EVM = 0, - C6670_EVM, - C6678_EVM, - TCI6614_EVM, - C6657_EVM, - UNKNOWN -}TDSP_Board_Type; - -extern TDSP_Board_Type gDSP_board_type; - -static inline TDSP_Board_Type KeyStone_Get_dsp_board_type() -{ - Uint32 deviceID= gpBootCfgRegs->DEVICE_ID_REG0&0x0FFFFFFF; - - gDSP_board_type= UNKNOWN; - if(0x0009D02F == deviceID) - gDSP_board_type= DUAL_NYQUIST_EVM; - if(0x0B94102F == deviceID) - { - gDSP_board_type= C6670_EVM; - //DSP_Board_Type= DUAL_NYQUIST_EVM; - } - if(0x0009E02F == deviceID) - gDSP_board_type= C6678_EVM; - if(0x0B96202F == deviceID) - gDSP_board_type= TCI6614_EVM; - if(0x0B97A02F == deviceID) - gDSP_board_type= C6657_EVM; - - return gDSP_board_type; -} - -static inline Uint32 KeyStone_Get_DSP_Number() -{ - TDSP_Board_Type DSP_Board_Type= KeyStone_Get_dsp_board_type(); - - if(DUAL_NYQUIST_EVM==DSP_Board_Type) - { - /*Nyquist EVM use boot configure pin 4 and 5 to identify DSPs*/ - return (( gpBootCfgRegs->BOOT_REG0 >> (3+1) ) & 0x03); - } - - /*if use DNUM to differentiate DSPs for two DSPs test, - the program must be run on core 0 of DSP 0 and core 1 of DSP1*/ - return DNUM; -} - -/*clear all interrupt flag/status, setup ISTP to begining of LL2*/ -extern void CPU_interrupt_init(); -/*enable interrupt to CPU: IER |= uiIER_en_mask; GIE=1*/ -extern void CPU_interrupt_enable(Uint32 uiIER_en_mask); - -//get device speed grade from the EFUSE register -extern void KeyStone_get_device_speed_grade(); - -/*Get device information including device type, boot mode, endian information, -speed grade, required voltage...*/ -extern void KeyStone_get_device_info(); - -/*common initialization for internal modules in K2 device. -enable memory protection interrupts, EDC for MSMC RAM*/ -extern void KeyStone_common_device_init(); - -/* enable TSC, EDC for local RAM; clear cache; protect L1 as cache */ -extern void KeyStone_common_CPU_init(); - - -#endif diff --git a/bsp/ti-c6678/.ccsproject b/bsp/ti-tms320c6678/.ccsproject similarity index 100% rename from bsp/ti-c6678/.ccsproject rename to bsp/ti-tms320c6678/.ccsproject diff --git a/bsp/ti-c6678/.cproject b/bsp/ti-tms320c6678/.cproject similarity index 100% rename from bsp/ti-c6678/.cproject rename to bsp/ti-tms320c6678/.cproject diff --git a/bsp/ti-c6678/.project b/bsp/ti-tms320c6678/.project similarity index 100% rename from bsp/ti-c6678/.project rename to bsp/ti-tms320c6678/.project diff --git a/bsp/ti-c6678/.settings/org.eclipse.cdt.codan.core.prefs b/bsp/ti-tms320c6678/.settings/org.eclipse.cdt.codan.core.prefs similarity index 100% rename from bsp/ti-c6678/.settings/org.eclipse.cdt.codan.core.prefs rename to bsp/ti-tms320c6678/.settings/org.eclipse.cdt.codan.core.prefs diff --git a/bsp/ti-c6678/.settings/org.eclipse.cdt.debug.core.prefs b/bsp/ti-tms320c6678/.settings/org.eclipse.cdt.debug.core.prefs similarity index 100% rename from bsp/ti-c6678/.settings/org.eclipse.cdt.debug.core.prefs rename to bsp/ti-tms320c6678/.settings/org.eclipse.cdt.debug.core.prefs diff --git a/bsp/ti-c6678/.settings/org.eclipse.core.resources.prefs b/bsp/ti-tms320c6678/.settings/org.eclipse.core.resources.prefs similarity index 100% rename from bsp/ti-c6678/.settings/org.eclipse.core.resources.prefs rename to bsp/ti-tms320c6678/.settings/org.eclipse.core.resources.prefs diff --git a/bsp/ti-c6678/KeyStone.cmd b/bsp/ti-tms320c6678/KeyStone.cmd similarity index 100% rename from bsp/ti-c6678/KeyStone.cmd rename to bsp/ti-tms320c6678/KeyStone.cmd diff --git a/bsp/ti-c6678/applications/board.c b/bsp/ti-tms320c6678/applications/board.c similarity index 63% rename from bsp/ti-c6678/applications/board.c rename to bsp/ti-tms320c6678/applications/board.c index 140871fd75..a0f951d31e 100644 --- a/bsp/ti-c6678/applications/board.c +++ b/bsp/ti-tms320c6678/applications/board.c @@ -22,13 +22,13 @@ */ void rt_hw_systick_isr(void) { - /* enter interrupt */ - rt_interrupt_enter(); + /* enter interrupt */ + rt_interrupt_enter(); - rt_tick_increase(); + rt_tick_increase(); - /* leave interrupt */ - rt_interrupt_leave(); + /* leave interrupt */ + rt_interrupt_leave(); } /** @@ -46,15 +46,12 @@ void rt_hw_board_init(void) rt_trap_init(); // initial system timer - hw_system_timer_init(); + hw_system_timer_init(); -#ifdef RT_USING_HEAP - /* initialize memory system */ - rt_kprintf("heap: 0x%08x - 0x%08x\n", RT_HW_HEAP_BEGIN, RT_HW_HEAP_END); - rt_system_heap_init(RT_HW_HEAP_BEGIN, RT_HW_HEAP_END); -#endif - // ...... + /* initialize memory system */ + rt_kprintf("heap: 0x%08x - 0x%08x\n", RT_HW_HEAP_BEGIN, RT_HW_HEAP_END); + rt_system_heap_init(RT_HW_HEAP_BEGIN, RT_HW_HEAP_END); - hw_system_timer_start(); + hw_system_timer_start(); } diff --git a/bsp/ti-c6678/applications/board.h b/bsp/ti-tms320c6678/applications/board.h similarity index 100% rename from bsp/ti-c6678/applications/board.h rename to bsp/ti-tms320c6678/applications/board.h diff --git a/bsp/ti-tms320c6678/applications/main.c b/bsp/ti-tms320c6678/applications/main.c new file mode 100644 index 0000000000..a8b9e17efc --- /dev/null +++ b/bsp/ti-tms320c6678/applications/main.c @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2021, Shenzhen Academy of Aerospace Technology + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2021-11-16 Dystopia the first version + */ + +#include +#include + +#include "board.h" + +void rt_init_thread_entry(void *parameter) +{ + rt_kprintf("hello rt-thread\n"); + return 0; +} + +int rt_application_init(void) +{ + rt_thread_t tid; + + tid = rt_thread_create("init", rt_init_thread_entry, RT_NULL, 4096, 3, 200); + if (tid != RT_NULL) + { + rt_thread_startup(tid); + } else { + return -1; + } + + return 0; +} + +/** + * This function will startup RT-Thread RTOS. + */ +void rtthread_startup(void) +{ + /* disable interrupt first */ + rt_hw_interrupt_disable(); + + /* init board */ + rt_hw_board_init(); + + /* show version */ + rt_show_version(); + + /* init timer system */ + rt_system_timer_init(); + + /* init scheduler system */ + rt_system_scheduler_init(); + + /* init application */ + rt_application_init(); + + /* init timer thread */ + rt_system_timer_thread_init(); + + /* init idle thread */ + rt_thread_idle_init(); + + /* start scheduler */ + rt_system_scheduler_start(); + + /* never reach here */ + return ; +} + +void main(void) +{ + /* startup RT-Thread RTOS */ + rtthread_startup(); + + for ( ; ; ); +} + diff --git a/bsp/ti-c6678/driver/drv_timer.c b/bsp/ti-tms320c6678/driver/drv_timer.c similarity index 100% rename from bsp/ti-c6678/driver/drv_timer.c rename to bsp/ti-tms320c6678/driver/drv_timer.c diff --git a/bsp/ti-c6678/driver/drv_timer.h b/bsp/ti-tms320c6678/driver/drv_timer.h similarity index 100% rename from bsp/ti-c6678/driver/drv_timer.h rename to bsp/ti-tms320c6678/driver/drv_timer.h diff --git a/bsp/ti-tms320c6678/readme.txt b/bsp/ti-tms320c6678/readme.txt new file mode 100644 index 0000000000..3309207357 --- /dev/null +++ b/bsp/ti-tms320c6678/readme.txt @@ -0,0 +1,3 @@ + 本工程使用TI公司编译器CCS5.5进行编译,工程中使用到了TI官方提供的K1_STK_v1.1, +如有需要的请到TI官方论坛自行下载,并将K1_STK_v1.1中的KeyStone_common.c和KeyStone_common.h文件 +放置到本工程的driver目录下。 \ No newline at end of file diff --git a/bsp/ti-c6678/rtconfig.h b/bsp/ti-tms320c6678/rtconfig.h similarity index 100% rename from bsp/ti-c6678/rtconfig.h rename to bsp/ti-tms320c6678/rtconfig.h diff --git a/bsp/ti-c6678/rtconfig_project.h b/bsp/ti-tms320c6678/rtconfig_project.h similarity index 100% rename from bsp/ti-c6678/rtconfig_project.h rename to bsp/ti-tms320c6678/rtconfig_project.h diff --git a/libcpu/ti-dsp/c6x/c66xx.h b/libcpu/ti-dsp/c6x/c66xx.h index 9f3a20399f..97d817a6d2 100644 --- a/libcpu/ti-dsp/c6x/c66xx.h +++ b/libcpu/ti-dsp/c6x/c66xx.h @@ -91,14 +91,13 @@ extern cregister volatile unsigned int DNUM; /* Core number */ #define __dint() asm(" DINT") #define __rint() asm(" RINT") - #define __system_call() asm(" SWE") #define __enter_idle() asm(" IDLE") #define __nop() asm(" NOP") #define __mfence() asm(" MFENCE") -#define __SYSREG(ADDR, TYPE) (*(volatile TYPE*)(ADDR)) -#define __SYSREGA(ADDR, TYPE) ((volatile TYPE*)(ADDR)) +#define __SYSREG(ADDR, TYPE) (*(volatile TYPE*)(ADDR)) +#define __SYSREGA(ADDR, TYPE) ((volatile TYPE*)(ADDR)) extern void rt_hw_enable_exception(void); diff --git a/libcpu/ti-dsp/c6x/context.asm b/libcpu/ti-dsp/c6x/context.asm index 07affb6a1a..f6972013f5 100644 --- a/libcpu/ti-dsp/c6x/context.asm +++ b/libcpu/ti-dsp/c6x/context.asm @@ -12,12 +12,17 @@ ; context switch for C6678 DSP ;----------------------------------------------------------- + .include "contextinc.asm" ;----------------------------------------------------------- ; macro definition ;----------------------------------------------------------- DP .set B14 SP .set B15 +;----------------------------------------------------------- +; extern variable +;----------------------------------------------------------- + .ref rt_system_stack_top ; ;----------------------------------------------------------- ; @@ -28,7 +33,6 @@ SP .set B15 .global rt_interrupt_from_thread .global rt_interrupt_to_thread .global rt_thread_switch_interrupt_flag - ; ;----------------------------------------------------------- ; @@ -100,18 +104,17 @@ rt_hw_context_switch: STDW .D2T2 B13:B12,*SP--[1] ; Store PC:CSR || MVC .S2 TSR,B5 - MVC ILC,B11 ; - MVC RILC,B10 ; + MVC .S2 ILC,B11 ; + MVC .S2 RILC,B10 ; STDW .D2T2 B11:B10,*SP--[1] ; Store RILC:ILC || MV .S1X B5,A3 ZERO A2 ; STDW .D2T1 A3:A2,*SP--[1] ; Store TSR:stack type STW SP,*A4 ; Save thread's stack pointer - - MV B4,A4 ; B rt_hw_context_switch_to - NOP 5 + MV B4,A4 ; + NOP 4 ;} ; @@ -138,13 +141,13 @@ rt_hw_context_switch_to: MV B13,B3 ; Restore PC MVC .S2 B12,CSR ; Restore CSR - LDDW *++SP[1],B11:B10 - LDDW *++SP[1],B13:B12 - LDDW *++SP[1],A11:A10 - LDDW *++SP[1],A13:A12 - LDDW *++SP[1],A15:A14 + LDDW .D2T2 *++SP[1],B11:B10 + LDDW .D2T2 *++SP[1],B13:B12 + LDDW .D2T1 *++SP[1],A11:A10 + LDDW .D2T1 *++SP[1],A13:A12 + LDDW .D2T1 *++SP[1],A15:A14 B B3 ; Return to caller - ADDAW SP,2,SP + ADDAW .D2 SP,2,SP NOP 4 ; Delay slots _rt_thread_interrupt_stack: ADDAW .D1X SP,30,A15 @@ -204,6 +207,7 @@ _rt_thread_interrupt_stack: ; void rt_hw_context_switch_interrupt(rt_uint32_t from, rt_uint32_t to) ; A4 --> from ; B4 --> to +;{ .global rt_hw_context_switch_interrupt rt_hw_context_switch_interrupt: SUB B15,0x8,B15 @@ -285,14 +289,26 @@ rt_interrupt_context_restore: || LDDW .D2T2 *++SP[1],B13:B12 MV .D2X A15,SP + || MVKL .S1 rt_system_stack_top,A15 + MVKH .S1 rt_system_stack_top,A15 + || ADDAW .D1X SP,6,A14 + STW .D1T1 A14,*A15 ; save system stack pointer + LDDW .D2T1 *++SP[1],A15:A14 B .S2 IRP ; return from interruption LDDW .D2T2 *+SP[1],SP:DP NOP 4 - rt_preempt_context_restore: ZERO A12 - STW A12,*A3 ; clear rt_thread_switch_interrupt_flag + STW A12,*A3 ; clear rt_thread_switch_interrupt_flag +; +; restore saved registers by system stack +; + RESTORE_ALL IRP,ITSR +; +; store registers to thread stack +; + THREAD_SAVE_ALL IRP,ITSR MVKL rt_interrupt_from_thread,A11 MVKH rt_interrupt_from_thread,A11 @@ -302,10 +318,10 @@ rt_preempt_context_restore: MVKH rt_interrupt_to_thread,B10 LDW *B10,B11 NOP 3 - STW SP,*A10 ; store sp in preempted tasks's TCB - MV B11,A4 ; - B rt_hw_context_switch_to - NOP 5 + STW SP,*A10 ; store sp in preempted tasks's TCB + B rt_hw_context_switch_to + MV B11,A4 ; + NOP 4 ;} .end diff --git a/libcpu/ti-dsp/c6x/contextinc.asm b/libcpu/ti-dsp/c6x/contextinc.asm new file mode 100644 index 0000000000..18926aa088 --- /dev/null +++ b/libcpu/ti-dsp/c6x/contextinc.asm @@ -0,0 +1,187 @@ +; +; Copyright (c) 2021, Shenzhen Academy of Aerospace Technology +; +; SPDX-License-Identifier: Apache-2.0 +; +; Change Logs: +; Date Author Notes +; 2021-11-16 Dystopia the first version +; + +;----------------------------------------------------------- +; macro definition +;----------------------------------------------------------- +SAVE_ALL .macro __rp, __tsr + STW .D2T2 B0,*SP--[2] ; save original B0 + MVKL .S2 rt_system_stack_top,B0 + MVKH .S2 rt_system_stack_top,B0 + LDW .D2T2 *B0,B1 ; system stack + + NOP 3 + STW .D2T2 B1,*+SP[1] ; save original B1 + XOR .D2 SP,B1,B0 ; (SP ^ KSP, check current stack types) + LDW .D2T2 *+SP[1],B1 ; restore B0/B1 + LDW .D2T2 *++SP[2],B0 + SHR .S2 B0,12,B0 ; 0 if already using system stack + [B0] STDW .D2T2 SP:DP,*--B1[1] ; thread: save thread sp/dp system stack + [B0] MV .S2 B1,SP ; and switch to system stack +||[!B0] STDW .D2T2 SP:DP,*--SP[1] ; kernel: nest interrupt save(not support) + + SUBAW .D2 SP,2,SP + + ADD .D1X SP,-8,A15 + || STDW .D2T1 A15:A14,*SP--[16] ; save A15:A14 + + STDW .D2T2 B13:B12,*SP--[1] + || STDW .D1T1 A13:A12,*A15--[1] + || MVC .S2 __rp,B13 + STDW .D2T2 B11:B10,*SP--[1] + || STDW .D1T1 A11:A10,*A15--[1] + || MVC .S2 CSR,B12 + + STDW .D2T2 B9:B8,*SP--[1] + || STDW .D1T1 A9:A8,*A15--[1] + || MVC .S2 RILC,B11 + STDW .D2T2 B7:B6,*SP--[1] + || STDW .D1T1 A7:A6,*A15--[1] + || MVC .S2 ILC,B10 + STDW .D2T2 B5:B4,*SP--[1] + || STDW .D1T1 A5:A4,*A15--[1] + STDW .D2T2 B3:B2,*SP--[1] + || STDW .D1T1 A3:A2,*A15--[1] + || MVC .S2 __tsr,B5 + STDW .D2T2 B1:B0,*SP--[1] + || STDW .D1T1 A1:A0,*A15--[1] + || MV .S1X B5,A5 + + STDW .D2T2 B31:B30,*SP--[1] + || STDW .D1T1 A31:A30,*A15--[1] + || MVKL 1,A4 + + STDW .D2T2 B29:B28,*SP--[1] + || STDW .D1T1 A29:A28,*A15--[1] + STDW .D2T2 B27:B26,*SP--[1] + || STDW .D1T1 A27:A26,*A15--[1] + STDW .D2T2 B25:B24,*SP--[1] + || STDW .D1T1 A25:A24,*A15--[1] + STDW .D2T2 B23:B22,*SP--[1] + || STDW .D1T1 A23:A22,*A15--[1] + STDW .D2T2 B21:B20,*SP--[1] + || STDW .D1T1 A21:A20,*A15--[1] + STDW .D2T2 B19:B18,*SP--[1] + || STDW .D1T1 A19:A18,*A15--[1] + STDW .D2T2 B17:B16,*SP--[1] + || STDW .D1T1 A17:A16,*A15--[1] + + STDW .D2T2 B13:B12,*SP--[1] ; save PC and CSR + STDW .D2T2 B11:B10,*SP--[1] ; save RILC and ILC + STDW .D2T1 A5:A4,*SP--[1] ; save TSR and orig A4 + .endm + +RESTORE_ALL .macro __rp, __tsr + LDDW .D2T2 *++SP[1],B9:B8 ; get TSR (B9) + LDDW .D2T2 *++SP[1],B11:B10 ; get RILC (B11) and ILC (B10) + LDDW .D2T2 *++SP[1],B13:B12 ; get PC (B13) and CSR (B12) + + ADDAW .D1X SP,30,A15 + + LDDW .D1T1 *++A15[1],A17:A16 + || LDDW .D2T2 *++SP[1],B17:B16 + LDDW .D1T1 *++A15[1],A19:A18 + || LDDW .D2T2 *++SP[1],B19:B18 + LDDW .D1T1 *++A15[1],A21:A20 + || LDDW .D2T2 *++SP[1],B21:B20 + LDDW .D1T1 *++A15[1],A23:A22 + || LDDW .D2T2 *++SP[1],B23:B22 + LDDW .D1T1 *++A15[1],A25:A24 + || LDDW .D2T2 *++SP[1],B25:B24 + LDDW .D1T1 *++A15[1],A27:A26 + || LDDW .D2T2 *++SP[1],B27:B26 + LDDW .D1T1 *++A15[1],A29:A28 + || LDDW .D2T2 *++SP[1],B29:B28 + LDDW .D1T1 *++A15[1],A31:A30 + || LDDW .D2T2 *++SP[1],B31:B30 + + LDDW .D1T1 *++A15[1],A1:A0 + || LDDW .D2T2 *++SP[1],B1:B0 + LDDW .D1T1 *++A15[1],A3:A2 + || LDDW .D2T2 *++SP[1],B3:B2 + || MVC .S2 B9,__tsr + LDDW .D1T1 *++A15[1],A5:A4 + || LDDW .D2T2 *++SP[1],B5:B4 + || MVC .S2 B11,RILC + LDDW .D1T1 *++A15[1],A7:A6 + || LDDW .D2T2 *++SP[1],B7:B6 + || MVC .S2 B10,ILC + LDDW .D1T1 *++A15[1],A9:A8 + || LDDW .D2T2 *++SP[1],B9:B8 + || MVC .S2 B13,__rp + + LDDW .D1T1 *++A15[1],A11:A10 + || LDDW .D2T2 *++SP[1],B11:B10 + || MVC .S2 B12,CSR + LDDW .D1T1 *++A15[1],A13:A12 + || LDDW .D2T2 *++SP[1],B13:B12 + + MV .D2X A15,SP + || MVKL .S1 rt_system_stack_top,A15 + MVKH .S1 rt_system_stack_top,A15 + || ADDAW .D1X SP,6,A14 + STW .D1T1 A14,*A15 ; save system stack pointer + + LDDW .D2T1 *++SP[1],A15:A14 + LDDW .D2T2 *+SP[1],SP:DP + NOP 4 + .endm + +THREAD_SAVE_ALL .macro __rp, __tsr + STDW .D2T2 SP:DP,*--SP[1] + SUBAW .D2 SP,2,SP + + ADD .D1X SP,-8,A15 + || STDW .D2T1 A15:A14,*SP--[16] ; save A15:A14 + + STDW .D2T2 B13:B12,*SP--[1] + || STDW .D1T1 A13:A12,*A15--[1] + || MVC .S2 __rp,B13 + STDW .D2T2 B11:B10,*SP--[1] + || STDW .D1T1 A11:A10,*A15--[1] + || MVC .S2 CSR,B12 + + STDW .D2T2 B9:B8,*SP--[1] + || STDW .D1T1 A9:A8,*A15--[1] + || MVC .S2 RILC,B11 + STDW .D2T2 B7:B6,*SP--[1] + || STDW .D1T1 A7:A6,*A15--[1] + || MVC .S2 ILC,B10 + STDW .D2T2 B5:B4,*SP--[1] + || STDW .D1T1 A5:A4,*A15--[1] + STDW .D2T2 B3:B2,*SP--[1] + || STDW .D1T1 A3:A2,*A15--[1] + || MVC .S2 __tsr,B5 + STDW .D2T2 B1:B0,*SP--[1] + || STDW .D1T1 A1:A0,*A15--[1] + || MV .S1X B5,A5 + + STDW .D2T2 B31:B30,*SP--[1] + || STDW .D1T1 A31:A30,*A15--[1] + || MVKL 1,A4 + STDW .D2T2 B29:B28,*SP--[1] + || STDW .D1T1 A29:A28,*A15--[1] + STDW .D2T2 B27:B26,*SP--[1] + || STDW .D1T1 A27:A26,*A15--[1] + STDW .D2T2 B25:B24,*SP--[1] + || STDW .D1T1 A25:A24,*A15--[1] + STDW .D2T2 B23:B22,*SP--[1] + || STDW .D1T1 A23:A22,*A15--[1] + STDW .D2T2 B21:B20,*SP--[1] + || STDW .D1T1 A21:A20,*A15--[1] + STDW .D2T2 B19:B18,*SP--[1] + || STDW .D1T1 A19:A18,*A15--[1] + STDW .D2T2 B17:B16,*SP--[1] + || STDW .D1T1 A17:A16,*A15--[1] + + STDW .D2T2 B13:B12,*SP--[1] ; save PC and CSR + STDW .D2T2 B11:B10,*SP--[1] ; save RILC and ILC + STDW .D2T1 A5:A4,*SP--[1] ; save TSR and orig A4 + .endm diff --git a/libcpu/ti-dsp/c6x/cpuport.c b/libcpu/ti-dsp/c6x/cpuport.c index a00a2e9046..716e8a16fa 100644 --- a/libcpu/ti-dsp/c6x/cpuport.c +++ b/libcpu/ti-dsp/c6x/cpuport.c @@ -27,7 +27,6 @@ RT_WEAK void rt_hw_cpu_shutdown(void) RT_ASSERT(0); } -//----------------------------------------------------------------------------- /*------------ nested_exception_handler() function --------------------------- * DESCRIPTION: Function handles Nested Exception @@ -40,8 +39,6 @@ void nested_exception_handler(void) { for ( ; ; ); } -//----------------------------------------------------------------------------- - /*------------ hw_nmi_handler() function -------------------------------------- * DESCRIPTION: Function handles NMI interrupt @@ -53,8 +50,6 @@ void hw_nmi_handler(struct rt_hw_exp_stack_register *regs) { for ( ; ; ); } -//----------------------------------------------------------------------------- - /*------------ hw_bad_handler() function -------------------------------------- * DESCRIPTION: Function handles Bad interrupt @@ -66,8 +61,6 @@ void hw_bad_handler(void) { for ( ; ; ); } -//----------------------------------------------------------------------------- - /*------------ hw_int4_handler() function ------------------------------------- * DESCRIPTION: Function handles INT4 interrupt @@ -79,8 +72,6 @@ void hw_int4_handler(void) { } -//----------------------------------------------------------------------------- - /*------------ hw_int5_handler() function ------------------------------------- * DESCRIPTION: Function handles INT5 interrupt @@ -92,8 +83,6 @@ void hw_int5_handler(void) { } -//----------------------------------------------------------------------------- - /*------------ hw_int6_handler() function ------------------------------------- * DESCRIPTION: Function handles INT6 interrupt @@ -105,8 +94,6 @@ void hw_int6_handler(void) { } -//----------------------------------------------------------------------------- - /*------------ hw_int7_handler() function ------------------------------------- * DESCRIPTION: Function handles INT7 interrupt @@ -118,8 +105,6 @@ void hw_int7_handler(void) { } -//----------------------------------------------------------------------------- - /*------------ hw_int8_handler() function ------------------------------------- * DESCRIPTION: Function handles INT8 interrupt @@ -131,8 +116,6 @@ void hw_int8_handler(void) { } -//----------------------------------------------------------------------------- - /*------------ hw_int9_handler() function ------------------------------------- * DESCRIPTION: Function handles INT9 interrupt @@ -144,8 +127,6 @@ void hw_int9_handler(void) { } -//----------------------------------------------------------------------------- - /*------------ hw_int10_handler() function ------------------------------------ * DESCRIPTION: Function handles INT10 interrupt @@ -157,8 +138,6 @@ void hw_int10_handler(void) { } -//----------------------------------------------------------------------------- - /*------------ hw_int11_handler() function ------------------------------------ * DESCRIPTION: Function handles INT11 interrupt @@ -170,8 +149,6 @@ void hw_int11_handler(void) { } -//----------------------------------------------------------------------------- - /*------------ hw_int12_handler() function ------------------------------------ * DESCRIPTION: Function handles INT12 interrupt @@ -181,9 +158,8 @@ void hw_int11_handler(void) -----------------------------------------------------------------------------*/ void hw_int12_handler(void) { + } -//----------------------------------------------------------------------------- - /*------------ hw_int13_handler() function ------------------------------------ * DESCRIPTION: Function handles INT13 interrupt @@ -195,8 +171,6 @@ void hw_int13_handler(void) { } -//----------------------------------------------------------------------------- - /*------------------ hw_int14_handler() function ------------------------------ * DESCRIPTION: Function handles INT14 interrupt @@ -209,8 +183,6 @@ void hw_int14_handler(void) extern void rt_hw_systick_isr(); rt_hw_systick_isr(); } -//----------------------------------------------------------------------------- - /*------------ hw_int15_handler() function ------------------------------------ * DESCRIPTION: Function handles INT15 interrupt diff --git a/libcpu/ti-dsp/c6x/interrupt.c b/libcpu/ti-dsp/c6x/interrupt.c index 69205e0d38..d78de95abb 100644 --- a/libcpu/ti-dsp/c6x/interrupt.c +++ b/libcpu/ti-dsp/c6x/interrupt.c @@ -8,7 +8,6 @@ * 2021-11-16 Dystopia the first version */ - #include "c66xx.h" #include "interrupt.h" diff --git a/libcpu/ti-dsp/c6x/inct.asm b/libcpu/ti-dsp/c6x/intexc.asm similarity index 69% rename from libcpu/ti-dsp/c6x/inct.asm rename to libcpu/ti-dsp/c6x/intexc.asm index 4f866e4800..d3ed54dc3b 100644 --- a/libcpu/ti-dsp/c6x/inct.asm +++ b/libcpu/ti-dsp/c6x/intexc.asm @@ -9,7 +9,7 @@ ; ;----------------------------------------------------------- -; interrupt handler for C6678 DSP +; interrupt and execption handler for C6678 DSP ;----------------------------------------------------------- ;----------------------------------------------------------- @@ -20,7 +20,7 @@ SP .set B15 ; ;----------------------------------------------------------- ; - + .include "contextinc.asm" ;----------------------------------------------------------- ; global function ;----------------------------------------------------------- @@ -65,121 +65,14 @@ SP .set B15 ;----------------------------------------------------------- ; +;----------------------------------------------------------- +; extern variable +;----------------------------------------------------------- + .ref rt_system_stack_top ; ;----------------------------------------------------------- ; -;----------------------------------------------------------- -; macro definition -;----------------------------------------------------------- -SAVE_ALL .macro __rp, __tsr - STDW .D2T2 SP:DP,*--SP[1] - SUBAW .D2 SP,2,SP - ADD .D1X SP,-8,A15 - || STDW .D2T1 A15:A14,*SP--[16] ; save A15:A14 - - STDW .D2T2 B13:B12,*SP--[1] - || STDW .D1T1 A13:A12,*A15--[1] - || MVC .S2 __rp,B13 - - STDW .D2T2 B11:B10,*SP--[1] - || STDW .D1T1 A11:A10,*A15--[1] - || MVC .S2 CSR,B12 - - STDW .D2T2 B9:B8,*SP--[1] - || STDW .D1T1 A9:A8,*A15--[1] - || MVC .S2 RILC,B11 - STDW .D2T2 B7:B6,*SP--[1] - || STDW .D1T1 A7:A6,*A15--[1] - || MVC .S2 ILC,B10 - - STDW .D2T2 B5:B4,*SP--[1] - || STDW .D1T1 A5:A4,*A15--[1] - - STDW .D2T2 B3:B2,*SP--[1] - || STDW .D1T1 A3:A2,*A15--[1] - || MVC .S2 __tsr,B5 - - STDW .D2T2 B1:B0,*SP--[1] - || STDW .D1T1 A1:A0,*A15--[1] - || MV .S1X B5,A5 - - STDW .D2T2 B31:B30,*SP--[1] - || STDW .D1T1 A31:A30,*A15--[1] - || MVKL 1,A4 - - STDW .D2T2 B29:B28,*SP--[1] - || STDW .D1T1 A29:A28,*A15--[1] - STDW .D2T2 B27:B26,*SP--[1] - || STDW .D1T1 A27:A26,*A15--[1] - STDW .D2T2 B25:B24,*SP--[1] - || STDW .D1T1 A25:A24,*A15--[1] - STDW .D2T2 B23:B22,*SP--[1] - || STDW .D1T1 A23:A22,*A15--[1] - STDW .D2T2 B21:B20,*SP--[1] - || STDW .D1T1 A21:A20,*A15--[1] - STDW .D2T2 B19:B18,*SP--[1] - || STDW .D1T1 A19:A18,*A15--[1] - STDW .D2T2 B17:B16,*SP--[1] - || STDW .D1T1 A17:A16,*A15--[1] - - STDW .D2T2 B13:B12,*SP--[1] ; save PC and CSR - - STDW .D2T2 B11:B10,*SP--[1] ; save RILC and ILC - STDW .D2T1 A5:A4,*SP--[1] ; save TSR and orig A4 - .endm - -RESTORE_ALL .macro __rp, __tsr - LDDW .D2T2 *++SP[1],B9:B8 ; get TSR (B9) - LDDW .D2T2 *++SP[1],B11:B10 ; get RILC (B11) and ILC (B10) - LDDW .D2T2 *++SP[1],B13:B12 ; get PC (B13) and CSR (B12) - - ADDAW .D1X SP,30,A15 - - LDDW .D1T1 *++A15[1],A17:A16 - || LDDW .D2T2 *++SP[1],B17:B16 - LDDW .D1T1 *++A15[1],A19:A18 - || LDDW .D2T2 *++SP[1],B19:B18 - LDDW .D1T1 *++A15[1],A21:A20 - || LDDW .D2T2 *++SP[1],B21:B20 - LDDW .D1T1 *++A15[1],A23:A22 - || LDDW .D2T2 *++SP[1],B23:B22 - LDDW .D1T1 *++A15[1],A25:A24 - || LDDW .D2T2 *++SP[1],B25:B24 - LDDW .D1T1 *++A15[1],A27:A26 - || LDDW .D2T2 *++SP[1],B27:B26 - LDDW .D1T1 *++A15[1],A29:A28 - || LDDW .D2T2 *++SP[1],B29:B28 - LDDW .D1T1 *++A15[1],A31:A30 - || LDDW .D2T2 *++SP[1],B31:B30 - - LDDW .D1T1 *++A15[1],A1:A0 - || LDDW .D2T2 *++SP[1],B1:B0 - LDDW .D1T1 *++A15[1],A3:A2 - || LDDW .D2T2 *++SP[1],B3:B2 - || MVC .S2 B9,__tsr - LDDW .D1T1 *++A15[1],A5:A4 - || LDDW .D2T2 *++SP[1],B5:B4 - || MVC .S2 B11,RILC - LDDW .D1T1 *++A15[1],A7:A6 - || LDDW .D2T2 *++SP[1],B7:B6 - || MVC .S2 B10,ILC - LDDW .D1T1 *++A15[1],A9:A8 - || LDDW .D2T2 *++SP[1],B9:B8 - || MVC .S2 B13,__rp - - LDDW .D1T1 *++A15[1],A11:A10 - || LDDW .D2T2 *++SP[1],B11:B10 - || MVC .S2 B12,CSR - LDDW .D1T1 *++A15[1],A13:A12 - || LDDW .D2T2 *++SP[1],B13:B12 - - MV .D2X A15,SP - LDDW .D2T1 *++SP[1],A15:A14 - B .S2 __rp ; return from interruption - LDDW .D2T2 *+SP[1],SP:DP - NOP 4 - .endm ;----------------------------------------------------------- ; interrupt macro definition ;----------------------------------------------------------- @@ -190,8 +83,8 @@ RT_INTERRUPT_ENTRY .macro RT_CALL_INT .macro __isr CALLP __isr,B3 B .S1 rt_interrupt_context_restore - NOP 5 - .endm + NOP 5 + .endm ;----------------------------------------------------------- ; execption macro definition ;----------------------------------------------------------- @@ -201,6 +94,8 @@ RT_EXECPTION_ENTRY .macro RT_EXECPTION_EXIT .macro RESTORE_ALL NRP,NTSR + B .S2 NRP ; return from interruption + NOP 5 .endm ; diff --git a/libcpu/ti-dsp/c6x/stack.asm b/libcpu/ti-dsp/c6x/stack.asm index 4415a9767c..6a523a1c95 100644 --- a/libcpu/ti-dsp/c6x/stack.asm +++ b/libcpu/ti-dsp/c6x/stack.asm @@ -13,7 +13,7 @@ ;----------------------------------------------------------- ;----------------------------------------------------------- -; macro definition +; macro definition ;----------------------------------------------------------- ADDRESS_MSK .set 0xFFFFFFF0 @@ -22,6 +22,10 @@ ADDRESS_MSK .set 0xFFFFFFF0 ; .sect ".text" +; +;----------------------------------------------------------- +; + ; ; rt_uint8_t *rt_hw_stack_init(void *tentry, void *parameter, rt_uint8_t *stack_addr, void *texit) ; tentry --> A4 diff --git a/libcpu/ti-dsp/c6x/trap.c b/libcpu/ti-dsp/c6x/trap.c index eb1863fa9c..f919467f2b 100644 --- a/libcpu/ti-dsp/c6x/trap.c +++ b/libcpu/ti-dsp/c6x/trap.c @@ -14,8 +14,18 @@ #include #include +#include + +#define RT_SYS_STACK_SIZE 4096 + +rt_uint8_t rt_system_stack[RT_SYS_STACK_SIZE]; +rt_uint8_t *rt_system_stack_top; + void rt_trap_init(void) { + rt_system_stack_top = &rt_system_stack[RT_SYS_STACK_SIZE-1]; + rt_system_stack_top = (rt_uint8_t *)RT_ALIGN_DOWN((rt_uint32_t)rt_system_stack_top, 8); + ack_exception(EXCEPT_TYPE_NXF); ack_exception(EXCEPT_TYPE_EXC); ack_exception(EXCEPT_TYPE_IXF); @@ -319,7 +329,7 @@ int rt_hw_process_exception(struct rt_hw_exp_stack_register *regs) int ie_num = 9; /* default is unknown exception */ while ((type = get_except_type()) != 0) { - type_num = fls(type) - 1; + type_num = __fls(type) - 1; switch(type_num) { case EXCEPT_TYPE_NXF: /* NMI exception */ diff --git a/libcpu/ti-dsp/c6x/trap.h b/libcpu/ti-dsp/c6x/trap.h index 5494fa900b..6d4312e243 100644 --- a/libcpu/ti-dsp/c6x/trap.h +++ b/libcpu/ti-dsp/c6x/trap.h @@ -67,8 +67,8 @@ struct rt_exception_info { #define BKPT_OPCODE 0x56454314 /* illegal opcode */ #define INTC_MEXPMASK __SYSREGA(0x018000e0, unsigned int) -#define __ffs(a) (_lmbd(1, _bitr(a))) -#define fls(a) (!(a) ? 0 : (32 - _lmbd(1, (a)))) +#define __ffs(a) (_lmbd(1, _bitr(a))) +#define __fls(a) (!(a) ? 0 : (32 - _lmbd(1, (a)))) void rt_trap_init(void); diff --git a/libcpu/ti-dsp/c6x/vector.asm b/libcpu/ti-dsp/c6x/vector.asm index 47eb8781f5..c942029d86 100644 --- a/libcpu/ti-dsp/c6x/vector.asm +++ b/libcpu/ti-dsp/c6x/vector.asm @@ -75,21 +75,21 @@ __name: .align 32 .global vector vector: - VEC_RESET _c_int00 - IRQVEC NMI, _nmi_handler - IRQVEC AINT, _bad_handler - IRQVEC MSGINT,_bad_handler - IRQVEC INT4, _int4_handler - IRQVEC INT5, _int5_handler - IRQVEC INT6, _int6_handler - IRQVEC INT7, _int7_handler - IRQVEC INT8, _int8_handler - IRQVEC INT9, _int9_handler - IRQVEC INT10, _int10_handler - IRQVEC INT11, _int11_handler - IRQVEC INT12, _int12_handler - IRQVEC INT13, _int13_handler - IRQVEC INT14, _int14_handler - IRQVEC INT15, _int15_handler + VEC_RESET _c_int00 + IRQVEC NMI, _nmi_handler + IRQVEC AINT, _bad_handler + IRQVEC MSGINT, _bad_handler + IRQVEC INT4, _int4_handler + IRQVEC INT5, _int5_handler + IRQVEC INT6, _int6_handler + IRQVEC INT7, _int7_handler + IRQVEC INT8, _int8_handler + IRQVEC INT9, _int9_handler + IRQVEC INT10, _int10_handler + IRQVEC INT11, _int11_handler + IRQVEC INT12, _int12_handler + IRQVEC INT13, _int13_handler + IRQVEC INT14, _int14_handler + IRQVEC INT15, _int15_handler .end From cbc0e1ffcf4ad79d08ab199e2529941fa8c510d1 Mon Sep 17 00:00:00 2001 From: Huang bo Date: Wed, 17 Nov 2021 18:31:58 +0800 Subject: [PATCH 03/24] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E6=A0=BC=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- bsp/ti-tms320c6678/applications/board.c | 30 +----- bsp/ti-tms320c6678/driver/drv_timer.c | 40 +++++--- libcpu/ti-dsp/c6x/c66xx.h | 18 ---- libcpu/ti-dsp/c6x/context.asm | 2 +- libcpu/ti-dsp/c6x/interrupt.c | 7 +- libcpu/ti-dsp/c6x/intexc.asm | 2 +- libcpu/ti-dsp/c6x/stack.asm | 122 ++++++++++++------------ libcpu/ti-dsp/c6x/trap.c | 1 + libcpu/ti-dsp/c6x/trap.h | 2 +- libcpu/ti-dsp/c6x/vector.asm | 2 +- 10 files changed, 102 insertions(+), 124 deletions(-) diff --git a/bsp/ti-tms320c6678/applications/board.c b/bsp/ti-tms320c6678/applications/board.c index a0f951d31e..0a96a82ff8 100644 --- a/bsp/ti-tms320c6678/applications/board.c +++ b/bsp/ti-tms320c6678/applications/board.c @@ -9,28 +9,12 @@ */ #include "board.h" -#include "trap.h" #include "interrupt.h" #include "drv_timer.h" #include "KeyStone_common.h" #include -/** - * This is the timer interrupt service routine. - * - */ -void rt_hw_systick_isr(void) -{ - /* enter interrupt */ - rt_interrupt_enter(); - - rt_tick_increase(); - - /* leave interrupt */ - rt_interrupt_leave(); -} - /** * This function will initial board. */ @@ -42,16 +26,12 @@ void rt_hw_board_init(void) // initial interrupt controller rt_hw_interrupt_init(); - // initial system trap - rt_trap_init(); - // initial system timer - hw_system_timer_init(); + hw_system_timer_init(); - /* initialize memory system */ - rt_kprintf("heap: 0x%08x - 0x%08x\n", RT_HW_HEAP_BEGIN, RT_HW_HEAP_END); - rt_system_heap_init(RT_HW_HEAP_BEGIN, RT_HW_HEAP_END); + /* initialize memory system */ + rt_kprintf("heap: 0x%08x - 0x%08x\n", RT_HW_HEAP_BEGIN, RT_HW_HEAP_END); + rt_system_heap_init(RT_HW_HEAP_BEGIN, RT_HW_HEAP_END); - hw_system_timer_start(); + hw_system_timer_start(); } - diff --git a/bsp/ti-tms320c6678/driver/drv_timer.c b/bsp/ti-tms320c6678/driver/drv_timer.c index 4cda450e49..163d802aca 100644 --- a/bsp/ti-tms320c6678/driver/drv_timer.c +++ b/bsp/ti-tms320c6678/driver/drv_timer.c @@ -15,41 +15,51 @@ #include /** - * @b Description - * @n - * The function initial system timer. - * Use local timer (==DNUM of a core) to generate a clock on TIMO0,interrupts are generated as well + * This is the timer interrupt service routine. * - * @param[] - * - * @retval - * NULL + */ +void rt_hw_systick_isr(void) +{ + /* enter interrupt */ + rt_interrupt_enter(); + + rt_tick_increase(); + + /* leave interrupt */ + rt_interrupt_leave(); +} + +/** + * The function initial system timer interrupt. */ void hw_system_timer_init(void) { - // initial system timer interrupt - // map local timer interrupt to INT14 + // initial system timer interrupt, map local timer interrupt to INT14 gpCGEM_regs->INTMUX3 = (CSL_GEM_TINTLN<TOUTSEL = (DNUM*2)< Date: Wed, 17 Nov 2021 18:44:00 +0800 Subject: [PATCH 04/24] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E6=A0=BC=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- bsp/ti-tms320c6678/applications/board.c | 4 ++-- bsp/ti-tms320c6678/driver/drv_timer.c | 4 ++-- bsp/ti-tms320c6678/driver/drv_timer.h | 4 ++-- libcpu/ti-dsp/c6x/c66xx.h | 7 ------- libcpu/ti-dsp/c6x/context.asm | 2 +- 5 files changed, 7 insertions(+), 14 deletions(-) diff --git a/bsp/ti-tms320c6678/applications/board.c b/bsp/ti-tms320c6678/applications/board.c index 0a96a82ff8..b6a4105599 100644 --- a/bsp/ti-tms320c6678/applications/board.c +++ b/bsp/ti-tms320c6678/applications/board.c @@ -27,11 +27,11 @@ void rt_hw_board_init(void) rt_hw_interrupt_init(); // initial system timer - hw_system_timer_init(); + rt_hw_system_timer_init(); /* initialize memory system */ rt_kprintf("heap: 0x%08x - 0x%08x\n", RT_HW_HEAP_BEGIN, RT_HW_HEAP_END); rt_system_heap_init(RT_HW_HEAP_BEGIN, RT_HW_HEAP_END); - hw_system_timer_start(); + rt_hw_system_timer_start(); } diff --git a/bsp/ti-tms320c6678/driver/drv_timer.c b/bsp/ti-tms320c6678/driver/drv_timer.c index 163d802aca..330e04dcde 100644 --- a/bsp/ti-tms320c6678/driver/drv_timer.c +++ b/bsp/ti-tms320c6678/driver/drv_timer.c @@ -32,7 +32,7 @@ void rt_hw_systick_isr(void) /** * The function initial system timer interrupt. */ -void hw_system_timer_init(void) +void rt_hw_system_timer_init(void) { // initial system timer interrupt, map local timer interrupt to INT14 gpCGEM_regs->INTMUX3 = (CSL_GEM_TINTLN< Date: Wed, 17 Nov 2021 18:48:54 +0800 Subject: [PATCH 05/24] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E6=A0=BC=E5=BC=8F,?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- libcpu/ti-dsp/c6x/c66xx.h | 74 +++++++++++++++++++-------------------- 1 file changed, 37 insertions(+), 37 deletions(-) diff --git a/libcpu/ti-dsp/c6x/c66xx.h b/libcpu/ti-dsp/c6x/c66xx.h index a8b08438ee..cb106f2f6a 100644 --- a/libcpu/ti-dsp/c6x/c66xx.h +++ b/libcpu/ti-dsp/c6x/c66xx.h @@ -14,56 +14,56 @@ #include #ifdef _BIG_ENDIAN -#define REG_PAIR(odd, even) unsigned long odd; unsigned long even +#define RT_REG_PAIR(odd, even) unsigned long odd; unsigned long even #else -#define REG_PAIR(odd, even) unsigned long even; unsigned long odd +#define RT_REG_PAIR(odd, even) unsigned long even; unsigned long odd #endif struct rt_hw_register { - REG_PAIR(b17, b16); - REG_PAIR(b19, b18); - REG_PAIR(b21, b20); - REG_PAIR(b23, b22); - REG_PAIR(b25, b24); - REG_PAIR(b27, b26); - REG_PAIR(b29, b28); - REG_PAIR(b31, b30); + RT_REG_PAIR(b17, b16); + RT_REG_PAIR(b19, b18); + RT_REG_PAIR(b21, b20); + RT_REG_PAIR(b23, b22); + RT_REG_PAIR(b25, b24); + RT_REG_PAIR(b27, b26); + RT_REG_PAIR(b29, b28); + RT_REG_PAIR(b31, b30); - REG_PAIR(b1, b0); - REG_PAIR(b3, b2); - REG_PAIR(b5, b4); - REG_PAIR(b7, b6); - REG_PAIR(b9, b8); - REG_PAIR(b11, b10); - REG_PAIR(b13, b12); + RT_REG_PAIR(b1, b0); + RT_REG_PAIR(b3, b2); + RT_REG_PAIR(b5, b4); + RT_REG_PAIR(b7, b6); + RT_REG_PAIR(b9, b8); + RT_REG_PAIR(b11, b10); + RT_REG_PAIR(b13, b12); - REG_PAIR(a17, a16); - REG_PAIR(a19, a18); - REG_PAIR(a21, a20); - REG_PAIR(a23, a22); - REG_PAIR(a25, a24); - REG_PAIR(a27, a26); - REG_PAIR(a29, a28); - REG_PAIR(a31, a30); + RT_REG_PAIR(a17, a16); + RT_REG_PAIR(a19, a18); + RT_REG_PAIR(a21, a20); + RT_REG_PAIR(a23, a22); + RT_REG_PAIR(a25, a24); + RT_REG_PAIR(a27, a26); + RT_REG_PAIR(a29, a28); + RT_REG_PAIR(a31, a30); - REG_PAIR(a1, a0); - REG_PAIR(a3, a2); - REG_PAIR(a5, a4); - REG_PAIR(a7, a6); - REG_PAIR(a9, a8); - REG_PAIR(a11, a10); - REG_PAIR(a13, a12); + RT_REG_PAIR(a1, a0); + RT_REG_PAIR(a3, a2); + RT_REG_PAIR(a5, a4); + RT_REG_PAIR(a7, a6); + RT_REG_PAIR(a9, a8); + RT_REG_PAIR(a11, a10); + RT_REG_PAIR(a13, a12); - REG_PAIR(a15, a14); - REG_PAIR(sp, dp); + RT_REG_PAIR(a15, a14); + RT_REG_PAIR(sp, dp); }; struct rt_hw_exp_stack_register { - REG_PAIR(tsr, orig_a4); - REG_PAIR(rilc, ilc); - REG_PAIR(pc, csr); + RT_REG_PAIR(tsr, orig_a4); + RT_REG_PAIR(rilc, ilc); + RT_REG_PAIR(pc, csr); struct rt_hw_register hw_register; }; From 8ab19db7fa1aa1bd1d9a5c3724b4de6a04012f41 Mon Sep 17 00:00:00 2001 From: Huang bo Date: Thu, 18 Nov 2021 08:53:30 +0800 Subject: [PATCH 06/24] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E6=B1=87=E7=BC=96rt=5F?= =?UTF-8?q?hw=5Fcontext=5Fswitch=5Fto=E5=A4=84=E5=85=B3=E4=BA=8E=E6=97=B6?= =?UTF-8?q?=E9=97=B4=E6=A7=BD=E7=9A=84=E4=BD=BF=E7=94=A8=EF=BC=9B=E4=BF=AE?= =?UTF-8?q?=E6=94=B9=E6=A0=BC=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- libcpu/ti-dsp/c6x/context.asm | 10 ++- libcpu/ti-dsp/c6x/contextinc.asm | 6 +- libcpu/ti-dsp/c6x/intexc.asm | 6 +- libcpu/ti-dsp/c6x/stack.asm | 106 +++++++++++++++---------------- 4 files changed, 63 insertions(+), 65 deletions(-) diff --git a/libcpu/ti-dsp/c6x/context.asm b/libcpu/ti-dsp/c6x/context.asm index 2bbe0477f5..a66caf2736 100644 --- a/libcpu/ti-dsp/c6x/context.asm +++ b/libcpu/ti-dsp/c6x/context.asm @@ -136,15 +136,14 @@ rt_hw_context_switch_to: ; ; this maybe do better ; - MVC .S2 B11,RILC ; Restore RILC - MVC .S2 B10,ILC ; Restore ILC - MV B13,B3 ; Restore PC - MVC .S2 B12,CSR ; Restore CSR - LDDW .D2T2 *++SP[1],B11:B10 + || MVC .S2 B11,RILC ; Restore RILC LDDW .D2T2 *++SP[1],B13:B12 + || MVC .S2 B10,ILC ; Restore ILC LDDW .D2T1 *++SP[1],A11:A10 + || MV B13,B3 ; Restore PC LDDW .D2T1 *++SP[1],A13:A12 + || MVC .S2 B12,CSR ; Restore CSR LDDW .D2T1 *++SP[1],A15:A14 B B3 ; Return to caller ADDAW .D2 SP,2,SP @@ -236,7 +235,6 @@ _reswitch: .global rt_interrupt_context_restore rt_interrupt_context_restore: ;{ -; if rt_switch_interrupt_flag set, jump to rt_hw_context_switch_interrupt and don't return MVKL rt_thread_switch_interrupt_flag,A3 MVKH rt_thread_switch_interrupt_flag,A3 LDW *A3,A1 diff --git a/libcpu/ti-dsp/c6x/contextinc.asm b/libcpu/ti-dsp/c6x/contextinc.asm index 18926aa088..d89e66fd4d 100644 --- a/libcpu/ti-dsp/c6x/contextinc.asm +++ b/libcpu/ti-dsp/c6x/contextinc.asm @@ -19,7 +19,7 @@ SAVE_ALL .macro __rp, __tsr NOP 3 STW .D2T2 B1,*+SP[1] ; save original B1 - XOR .D2 SP,B1,B0 ; (SP ^ KSP, check current stack types) + XOR .D2 SP,B1,B0 ; check current stack types LDW .D2T2 *+SP[1],B1 ; restore B0/B1 LDW .D2T2 *++SP[2],B0 SHR .S2 B0,12,B0 ; 0 if already using system stack @@ -75,7 +75,7 @@ SAVE_ALL .macro __rp, __tsr STDW .D2T2 B13:B12,*SP--[1] ; save PC and CSR STDW .D2T2 B11:B10,*SP--[1] ; save RILC and ILC - STDW .D2T1 A5:A4,*SP--[1] ; save TSR and orig A4 + STDW .D2T1 A5:A4,*SP--[1] ; save TSR and orig A4(stack type) .endm RESTORE_ALL .macro __rp, __tsr @@ -183,5 +183,5 @@ THREAD_SAVE_ALL .macro __rp, __tsr STDW .D2T2 B13:B12,*SP--[1] ; save PC and CSR STDW .D2T2 B11:B10,*SP--[1] ; save RILC and ILC - STDW .D2T1 A5:A4,*SP--[1] ; save TSR and orig A4 + STDW .D2T1 A5:A4,*SP--[1] ; save TSR and orig A4(stack type) .endm diff --git a/libcpu/ti-dsp/c6x/intexc.asm b/libcpu/ti-dsp/c6x/intexc.asm index 709a9c4232..e5bfef4a2a 100644 --- a/libcpu/ti-dsp/c6x/intexc.asm +++ b/libcpu/ti-dsp/c6x/intexc.asm @@ -9,7 +9,7 @@ ; ;----------------------------------------------------------- -; interrupt and execption handler for C000 DSP +; interrupt and execption handler for C6000 DSP ;----------------------------------------------------------- ;----------------------------------------------------------- @@ -94,7 +94,7 @@ RT_EXECPTION_ENTRY .macro RT_EXECPTION_EXIT .macro RESTORE_ALL NRP,NTSR - B .S2 NRP ; return from interruption + B .S2 NRP ; return from execption NOP 5 .endm @@ -137,7 +137,7 @@ ret_from_trap: [!B0] MVKH .S2 ret_from_exception,B3 [!B0] BNOP .S2 B3,5 ; -; return from traprestore exception context +; return from trap restore exception context ; ret_from_exception: RT_EXECPTION_EXIT diff --git a/libcpu/ti-dsp/c6x/stack.asm b/libcpu/ti-dsp/c6x/stack.asm index 6823ef7a66..610f4f8f80 100644 --- a/libcpu/ti-dsp/c6x/stack.asm +++ b/libcpu/ti-dsp/c6x/stack.asm @@ -35,73 +35,73 @@ ADDRESS_MSK .set 0xFFFFFFF0 ;{ .global rt_hw_stack_init rt_hw_stack_init: - SUB A6,1,B1 ; - MVKL ADDRESS_MSK,A1 ; - MVKH ADDRESS_MSK,A1 ; Build address mask - MVC CSR,B0 ; - AND -2,B0,B0 ; Clear GIE bit - OR 2,B0,B0 ; Set PGIE bit for interrupt return - AND A1,B1,B1 ; Ensure alignment + SUB A6,1,B1 ; + MVKL .S1 ADDRESS_MSK,A1 ; + MVKH .S1 ADDRESS_MSK,A1 ; Build address mask + MVC .S2 CSR,B0 ; + AND -2,B0,B0 ; Clear GIE bit + OR 2,B0,B0 ; Set PGIE bit for interrupt return + AND A1,B1,B1 ; Ensure alignment ; ; Actually build the stack frame. ; - MV B1,A3 - MV B14,A2 - STDW A3:A2,*--B1[1] ; Initial B15:B14 + MV .S1 B1,A3 + MV .S1 B14,A2 + STDW .D2T1 A3:A2,*--B1[1] ; Initial B15:B14 SUBAW .D2 B1,2,B1 ZERO A2 - ZERO A3 ; Clear value - STDW A3:A2,*B1--[1] ; Initial A15:A14 - STDW A3:A2,*B1--[1] ; Initial A13:A12 - STDW A3:A2,*B1--[1] ; Initial A11:A10 - STDW A3:A2,*B1--[1] ; Initial A9:A8 - STDW A3:A2,*B1--[1] ; Initial A7:A6 - MV B4,A2 - STDW A3:A2,*B1--[1] ; Initial A5:A4 + ZERO A3 ; Clear value + STDW .D2T1 A3:A2,*B1--[1] ; Initial A15:A14 + STDW .D2T1 A3:A2,*B1--[1] ; Initial A13:A12 + STDW .D2T1 A3:A2,*B1--[1] ; Initial A11:A10 + STDW .D2T1 A3:A2,*B1--[1] ; Initial A9:A8 + STDW .D2T1 A3:A2,*B1--[1] ; Initial A7:A6 + MV .S1 B4,A2 + STDW .D2T1 A3:A2,*B1--[1] ; Initial A5:A4 ZERO A2 - STDW A3:A2,*B1--[1] ; Initial A3:A2 - STDW A3:A2,*B1--[1] ; Initial A1:A0 + STDW .D2T1 A3:A2,*B1--[1] ; Initial A3:A2 + STDW .D2T1 A3:A2,*B1--[1] ; Initial A1:A0 - STDW A3:A2,*B1--[1] ; Initial A31:A30 - STDW A3:A2,*B1--[1] ; Initial A29:A28 - STDW A3:A2,*B1--[1] ; Initial A27:A26 - STDW A3:A2,*B1--[1] ; Initial A25:A24 - STDW A3:A2,*B1--[1] ; Initial A23:A22 - STDW A3:A2,*B1--[1] ; Initial A21:A20 - STDW A3:A2,*B1--[1] ; Initial A19:A18 - STDW A3:A2,*B1--[1] ; Initial A17:A16 + STDW .D2T1 A3:A2,*B1--[1] ; Initial A31:A30 + STDW .D2T1 A3:A2,*B1--[1] ; Initial A29:A28 + STDW .D2T1 A3:A2,*B1--[1] ; Initial A27:A26 + STDW .D2T1 A3:A2,*B1--[1] ; Initial A25:A24 + STDW .D2T1 A3:A2,*B1--[1] ; Initial A23:A22 + STDW .D2T1 A3:A2,*B1--[1] ; Initial A21:A20 + STDW .D2T1 A3:A2,*B1--[1] ; Initial A19:A18 + STDW .D2T1 A3:A2,*B1--[1] ; Initial A17:A16 - STDW A3:A2,*B1--[1] ; Initial B13:B12 - STDW A3:A2,*B1--[1] ; Initial B11:B10 - STDW A3:A2,*B1--[1] ; Initial B9:B8 - STDW A3:A2,*B1--[1] ; Initial B7:B6 - STDW A3:A2,*B1--[1] ; Initial B5:B4 - MV B6,A3 - STDW A3:A2,*B1--[1] ; Initial B3:B2 + STDW .D2T1 A3:A2,*B1--[1] ; Initial B13:B12 + STDW .D2T1 A3:A2,*B1--[1] ; Initial B11:B10 + STDW .D2T1 A3:A2,*B1--[1] ; Initial B9:B8 + STDW .D2T1 A3:A2,*B1--[1] ; Initial B7:B6 + STDW .D2T1 A3:A2,*B1--[1] ; Initial B5:B4 + MV .S1 B6,A3 + STDW .D2T1 A3:A2,*B1--[1] ; Initial B3:B2 ZERO A3 - STDW A3:A2,*B1--[1] ; Initial B1:B0 + STDW .D2T1 A3:A2,*B1--[1] ; Initial B1:B0 - STDW A3:A2,*B1--[1] ; Initial B31:B30 - STDW A3:A2,*B1--[1] ; Initial B29:B28 - STDW A3:A2,*B1--[1] ; Initial B27:B26 - STDW A3:A2,*B1--[1] ; Initial B25:B24 - STDW A3:A2,*B1--[1] ; Initial B23:B22 - STDW A3:A2,*B1--[1] ; Initial B21:B20 - STDW A3:A2,*B1--[1] ; Initial B19:B18 - STDW A3:A2,*B1--[1] ; Initial B17:B16 + STDW .D2T1 A3:A2,*B1--[1] ; Initial B31:B30 + STDW .D2T1 A3:A2,*B1--[1] ; Initial B29:B28 + STDW .D2T1 A3:A2,*B1--[1] ; Initial B27:B26 + STDW .D2T1 A3:A2,*B1--[1] ; Initial B25:B24 + STDW .D2T1 A3:A2,*B1--[1] ; Initial B23:B22 + STDW .D2T1 A3:A2,*B1--[1] ; Initial B21:B20 + STDW .D2T1 A3:A2,*B1--[1] ; Initial B19:B18 + STDW .D2T1 A3:A2,*B1--[1] ; Initial B17:B16 - MV A4,A3 - MV B0,A2 - STDW A3:A2,*B1--[1] ; Initial PC:CSR + MV .S1 A4,A3 + MV .S1 B0,A2 + STDW .D2T1 A3:A2,*B1--[1] ; Initial PC:CSR ZERO A2 ZERO A3 - STDW A3:A2,*B1--[1] ; Initial ILC:RILC + STDW .D2T1 A3:A2,*B1--[1] ; Initial ILC:RILC B B3 - MVKL 0x3,B0 - MV B0,A3 - MVKL 1,A2 - STDW A3:A2,*B1--[1] ; Initial TSR:stack type - MV B1,A4 ; Save to TCB + MVKL .S2 0x3,B0 + MV .S1 B0,A3 + MVKL .S1 1,A2 + STDW .D2T1 A3:A2,*B1--[1] ; Initial TSR:stack type + MV .S1 B1,A4 ; Save to TCB ;} .end From 2b13e2fa57a8cc2f536b8279eb0c952c6e3b49d7 Mon Sep 17 00:00:00 2001 From: Huang bo Date: Thu, 18 Nov 2021 09:23:29 +0800 Subject: [PATCH 07/24] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E6=A0=BC=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- bsp/ti-tms320c6678/applications/board.c | 10 +-- bsp/ti-tms320c6678/applications/main.c | 52 +++++++-------- bsp/ti-tms320c6678/driver/drv_timer.c | 12 ++-- libcpu/ti-dsp/c6x/c66xx.h | 88 ++++++++++++------------- libcpu/ti-dsp/c6x/context.asm | 80 +++++++++++----------- libcpu/ti-dsp/c6x/contextinc.asm | 44 ++++++------- libcpu/ti-dsp/c6x/cpuport.c | 1 - libcpu/ti-dsp/c6x/interrupt.c | 4 +- libcpu/ti-dsp/c6x/intexc.asm | 16 ++--- libcpu/ti-dsp/c6x/stack.asm | 88 ++++++++++++------------- libcpu/ti-dsp/c6x/trap.c | 12 ++-- libcpu/ti-dsp/c6x/trap.h | 28 ++++---- 12 files changed, 216 insertions(+), 219 deletions(-) diff --git a/bsp/ti-tms320c6678/applications/board.c b/bsp/ti-tms320c6678/applications/board.c index b6a4105599..51a21f6cd8 100644 --- a/bsp/ti-tms320c6678/applications/board.c +++ b/bsp/ti-tms320c6678/applications/board.c @@ -20,13 +20,13 @@ */ void rt_hw_board_init(void) { - // initial CPU core - KeyStone_common_CPU_init(); + // initial CPU core + KeyStone_common_CPU_init(); - // initial interrupt controller - rt_hw_interrupt_init(); + // initial interrupt controller + rt_hw_interrupt_init(); - // initial system timer + // initial system timer rt_hw_system_timer_init(); /* initialize memory system */ diff --git a/bsp/ti-tms320c6678/applications/main.c b/bsp/ti-tms320c6678/applications/main.c index a8b9e17efc..f72b93b9dc 100644 --- a/bsp/ti-tms320c6678/applications/main.c +++ b/bsp/ti-tms320c6678/applications/main.c @@ -15,8 +15,8 @@ void rt_init_thread_entry(void *parameter) { - rt_kprintf("hello rt-thread\n"); - return 0; + rt_kprintf("hello rt-thread\n"); + return 0; } int rt_application_init(void) @@ -39,42 +39,42 @@ int rt_application_init(void) */ void rtthread_startup(void) { - /* disable interrupt first */ - rt_hw_interrupt_disable(); + /* disable interrupt first */ + rt_hw_interrupt_disable(); + + /* init board */ + rt_hw_board_init(); - /* init board */ - rt_hw_board_init(); + /* show version */ + rt_show_version(); - /* show version */ - rt_show_version(); + /* init timer system */ + rt_system_timer_init(); - /* init timer system */ - rt_system_timer_init(); + /* init scheduler system */ + rt_system_scheduler_init(); - /* init scheduler system */ - rt_system_scheduler_init(); + /* init application */ + rt_application_init(); - /* init application */ - rt_application_init(); + /* init timer thread */ + rt_system_timer_thread_init(); - /* init timer thread */ - rt_system_timer_thread_init(); + /* init idle thread */ + rt_thread_idle_init(); - /* init idle thread */ - rt_thread_idle_init(); + /* start scheduler */ + rt_system_scheduler_start(); - /* start scheduler */ - rt_system_scheduler_start(); - - /* never reach here */ - return ; + /* never reach here */ + return ; } void main(void) { - /* startup RT-Thread RTOS */ - rtthread_startup(); + /* startup RT-Thread RTOS */ + rtthread_startup(); - for ( ; ; ); + for ( ; ; ); } diff --git a/bsp/ti-tms320c6678/driver/drv_timer.c b/bsp/ti-tms320c6678/driver/drv_timer.c index 330e04dcde..b2a9319875 100644 --- a/bsp/ti-tms320c6678/driver/drv_timer.c +++ b/bsp/ti-tms320c6678/driver/drv_timer.c @@ -20,13 +20,13 @@ */ void rt_hw_systick_isr(void) { - /* enter interrupt */ - rt_interrupt_enter(); + /* enter interrupt */ + rt_interrupt_enter(); - rt_tick_increase(); + rt_tick_increase(); - /* leave interrupt */ - rt_interrupt_leave(); + /* leave interrupt */ + rt_interrupt_leave(); } /** @@ -34,7 +34,7 @@ void rt_hw_systick_isr(void) */ void rt_hw_system_timer_init(void) { - // initial system timer interrupt, map local timer interrupt to INT14 + // initial system timer interrupt, map local timer interrupt to INT14 gpCGEM_regs->INTMUX3 = (CSL_GEM_TINTLN< Date: Thu, 18 Nov 2021 09:37:05 +0800 Subject: [PATCH 08/24] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E6=A0=BC=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- bsp/ti-tms320c6678/applications/main.c | 2 +- bsp/ti-tms320c6678/driver/drv_timer.c | 10 +- libcpu/ti-dsp/c6x/cpuport.c | 8 +- libcpu/ti-dsp/c6x/trap.c | 560 ++++++++++++------------- 4 files changed, 289 insertions(+), 291 deletions(-) diff --git a/bsp/ti-tms320c6678/applications/main.c b/bsp/ti-tms320c6678/applications/main.c index f72b93b9dc..d29fd00a4f 100644 --- a/bsp/ti-tms320c6678/applications/main.c +++ b/bsp/ti-tms320c6678/applications/main.c @@ -75,6 +75,6 @@ void main(void) /* startup RT-Thread RTOS */ rtthread_startup(); - for ( ; ; ); + for(;;){} } diff --git a/bsp/ti-tms320c6678/driver/drv_timer.c b/bsp/ti-tms320c6678/driver/drv_timer.c index b2a9319875..a755689df4 100644 --- a/bsp/ti-tms320c6678/driver/drv_timer.c +++ b/bsp/ti-tms320c6678/driver/drv_timer.c @@ -35,7 +35,7 @@ void rt_hw_systick_isr(void) void rt_hw_system_timer_init(void) { // initial system timer interrupt, map local timer interrupt to INT14 - gpCGEM_regs->INTMUX3 = (CSL_GEM_TINTLN<INTMUX3=(CSL_GEM_TINTLN<TOUTSEL = (DNUM*2)< -#define RT_SYS_STACK_SIZE 4096 +#define RT_SYS_STACK_SIZE 4096 extern void rt_hw_enable_exception(void); rt_uint8_t rt_system_stack[RT_SYS_STACK_SIZE]; @@ -24,111 +24,110 @@ rt_uint8_t *rt_system_stack_top; void rt_trap_init(void) { - rt_system_stack_top = &rt_system_stack[RT_SYS_STACK_SIZE-1]; - rt_system_stack_top = (rt_uint8_t *)RT_ALIGN_DOWN((rt_uint32_t)rt_system_stack_top, 8); + rt_system_stack_top = &rt_system_stack[RT_SYS_STACK_SIZE-1]; + rt_system_stack_top = (rt_uint8_t *)RT_ALIGN_DOWN((rt_uint32_t)rt_system_stack_top, 8); - ack_exception(EXCEPT_TYPE_NXF); - ack_exception(EXCEPT_TYPE_EXC); - ack_exception(EXCEPT_TYPE_IXF); - ack_exception(EXCEPT_TYPE_SXF); - rt_hw_enable_exception(); + ack_exception(EXCEPT_TYPE_NXF); + ack_exception(EXCEPT_TYPE_EXC); + ack_exception(EXCEPT_TYPE_IXF); + ack_exception(EXCEPT_TYPE_SXF); + rt_hw_enable_exception(); } void show_regs(struct rt_hw_exp_stack_register *regs) { - rt_kprintf("\n"); - rt_kprintf("PC: %08lx SP: %08lx\n", - regs->pc, regs->hw_register.sp); - rt_kprintf("Status: %08lx ORIG_A4: %08lx\n", - regs->csr, regs->orig_a4); - rt_kprintf("A0: %08lx B0: %08lx\n", - regs->hw_register.a0, regs->hw_register.b0); - rt_kprintf("A1: %08lx B1: %08lx\n", - regs->hw_register.a1, regs->hw_register.b1); - rt_kprintf("A2: %08lx B2: %08lx\n", - regs->hw_register.a2, regs->hw_register.b2); - rt_kprintf("A3: %08lx B3: %08lx\n", - regs->hw_register.a3, regs->hw_register.b3); - rt_kprintf("A4: %08lx B4: %08lx\n", - regs->hw_register.a4, regs->hw_register.b4); - rt_kprintf("A5: %08lx B5: %08lx\n", - regs->hw_register.a5, regs->hw_register.b5); - rt_kprintf("A6: %08lx B6: %08lx\n", - regs->hw_register.a6, regs->hw_register.b6); - rt_kprintf("A7: %08lx B7: %08lx\n", - regs->hw_register.a7, regs->hw_register.b7); - rt_kprintf("A8: %08lx B8: %08lx\n", - regs->hw_register.a8, regs->hw_register.b8); - rt_kprintf("A9: %08lx B9: %08lx\n", - regs->hw_register.a9, regs->hw_register.b9); - rt_kprintf("A10: %08lx B10: %08lx\n", - regs->hw_register.a10, regs->hw_register.b10); - rt_kprintf("A11: %08lx B11: %08lx\n", - regs->hw_register.a11, regs->hw_register.b11); - rt_kprintf("A12: %08lx B12: %08lx\n", - regs->hw_register.a12, regs->hw_register.b12); - rt_kprintf("A13: %08lx B13: %08lx\n", - regs->hw_register.a13, regs->hw_register.b13); - rt_kprintf("A14: %08lx B14: %08lx\n", - regs->hw_register.a14, regs->hw_register.dp); - rt_kprintf("A15: %08lx B15: %08lx\n", - regs->hw_register.a15, regs->hw_register.sp); - rt_kprintf("A16: %08lx B16: %08lx\n", - regs->hw_register.a16, regs->hw_register.b16); - rt_kprintf("A17: %08lx B17: %08lx\n", - regs->hw_register.a17, regs->hw_register.b17); - rt_kprintf("A18: %08lx B18: %08lx\n", - regs->hw_register.a18, regs->hw_register.b18); - rt_kprintf("A19: %08lx B19: %08lx\n", - regs->hw_register.a19, regs->hw_register.b19); - rt_kprintf("A20: %08lx B20: %08lx\n", - regs->hw_register.a20, regs->hw_register.b20); - rt_kprintf("A21: %08lx B21: %08lx\n", - regs->hw_register.a21, regs->hw_register.b21); - rt_kprintf("A22: %08lx B22: %08lx\n", - regs->hw_register.a22, regs->hw_register.b22); - rt_kprintf("A23: %08lx B23: %08lx\n", - regs->hw_register.a23, regs->hw_register.b23); - rt_kprintf("A24: %08lx B24: %08lx\n", - regs->hw_register.a24, regs->hw_register.b24); - rt_kprintf("A25: %08lx B25: %08lx\n", - regs->hw_register.a25, regs->hw_register.b25); - rt_kprintf("A26: %08lx B26: %08lx\n", - regs->hw_register.a26, regs->hw_register.b26); - rt_kprintf("A27: %08lx B27: %08lx\n", - regs->hw_register.a27, regs->hw_register.b27); - rt_kprintf("A28: %08lx B28: %08lx\n", - regs->hw_register.a28, regs->hw_register.b28); - rt_kprintf("A29: %08lx B29: %08lx\n", - regs->hw_register.a29, regs->hw_register.b29); - rt_kprintf("A30: %08lx B30: %08lx\n", - regs->hw_register.a30, regs->hw_register.b30); - rt_kprintf("A31: %08lx B31: %08lx\n", - regs->hw_register.a31, regs->hw_register.b31); + rt_kprintf("\n"); + rt_kprintf("PC: %08lx SP: %08lx\n", + regs->pc, regs->hw_register.sp); + rt_kprintf("Status: %08lx ORIG_A4: %08lx\n", + regs->csr, regs->orig_a4); + rt_kprintf("A0: %08lx B0: %08lx\n", + regs->hw_register.a0, regs->hw_register.b0); + rt_kprintf("A1: %08lx B1: %08lx\n", + regs->hw_register.a1, regs->hw_register.b1); + rt_kprintf("A2: %08lx B2: %08lx\n", + regs->hw_register.a2, regs->hw_register.b2); + rt_kprintf("A3: %08lx B3: %08lx\n", + regs->hw_register.a3, regs->hw_register.b3); + rt_kprintf("A4: %08lx B4: %08lx\n", + regs->hw_register.a4, regs->hw_register.b4); + rt_kprintf("A5: %08lx B5: %08lx\n", + regs->hw_register.a5, regs->hw_register.b5); + rt_kprintf("A6: %08lx B6: %08lx\n", + regs->hw_register.a6, regs->hw_register.b6); + rt_kprintf("A7: %08lx B7: %08lx\n", + regs->hw_register.a7, regs->hw_register.b7); + rt_kprintf("A8: %08lx B8: %08lx\n", + regs->hw_register.a8, regs->hw_register.b8); + rt_kprintf("A9: %08lx B9: %08lx\n", + regs->hw_register.a9, regs->hw_register.b9); + rt_kprintf("A10: %08lx B10: %08lx\n", + regs->hw_register.a10, regs->hw_register.b10); + rt_kprintf("A11: %08lx B11: %08lx\n", + regs->hw_register.a11, regs->hw_register.b11); + rt_kprintf("A12: %08lx B12: %08lx\n", + regs->hw_register.a12, regs->hw_register.b12); + rt_kprintf("A13: %08lx B13: %08lx\n", + regs->hw_register.a13, regs->hw_register.b13); + rt_kprintf("A14: %08lx B14: %08lx\n", + regs->hw_register.a14, regs->hw_register.dp); + rt_kprintf("A15: %08lx B15: %08lx\n", + regs->hw_register.a15, regs->hw_register.sp); + rt_kprintf("A16: %08lx B16: %08lx\n", + regs->hw_register.a16, regs->hw_register.b16); + rt_kprintf("A17: %08lx B17: %08lx\n", + regs->hw_register.a17, regs->hw_register.b17); + rt_kprintf("A18: %08lx B18: %08lx\n", + regs->hw_register.a18, regs->hw_register.b18); + rt_kprintf("A19: %08lx B19: %08lx\n", + regs->hw_register.a19, regs->hw_register.b19); + rt_kprintf("A20: %08lx B20: %08lx\n", + regs->hw_register.a20, regs->hw_register.b20); + rt_kprintf("A21: %08lx B21: %08lx\n", + regs->hw_register.a21, regs->hw_register.b21); + rt_kprintf("A22: %08lx B22: %08lx\n", + regs->hw_register.a22, regs->hw_register.b22); + rt_kprintf("A23: %08lx B23: %08lx\n", + regs->hw_register.a23, regs->hw_register.b23); + rt_kprintf("A24: %08lx B24: %08lx\n", + regs->hw_register.a24, regs->hw_register.b24); + rt_kprintf("A25: %08lx B25: %08lx\n", + regs->hw_register.a25, regs->hw_register.b25); + rt_kprintf("A26: %08lx B26: %08lx\n", + regs->hw_register.a26, regs->hw_register.b26); + rt_kprintf("A27: %08lx B27: %08lx\n", + regs->hw_register.a27, regs->hw_register.b27); + rt_kprintf("A28: %08lx B28: %08lx\n", + regs->hw_register.a28, regs->hw_register.b28); + rt_kprintf("A29: %08lx B29: %08lx\n", + regs->hw_register.a29, regs->hw_register.b29); + rt_kprintf("A30: %08lx B30: %08lx\n", + regs->hw_register.a30, regs->hw_register.b30); + rt_kprintf("A31: %08lx B31: %08lx\n", + regs->hw_register.a31, regs->hw_register.b31); } void do_trap(struct rt_exception_info *except_info, struct rt_hw_exp_stack_register *regs) { - rt_kprintf("Enter exception: %s\n", except_info->kernel_str); + rt_kprintf("Enter exception: %s\n", except_info->kernel_str); - show_regs(regs); + show_regs(regs); - for( ; ; ); + for(;;){} } - static struct rt_exception_info iexcept_table[10] = { - { " - instruction fetch", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, - { " - fetch packet", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, - { " - execute packet", ABORT_TYPE_UNDDEF, ABORT_OPCODE_ILL }, - { " - undefined instruction", ABORT_TYPE_UNDDEF, ABORT_OPCODE_ILL }, - { " - resource conflict", ABORT_TYPE_UNDDEF, ABORT_OPCODE_ILL }, - { " - resource access", ABORT_TYPE_UNDDEF, ABORT_PRVREG_ILL }, - { " - privilege", ABORT_TYPE_UNDDEF, ABORT_PRVOPC_ILL }, - { " - loops buffer", ABORT_TYPE_UNDDEF, ABORT_PRVOPC_ILL }, - { " - software exception", ABORT_TYPE_UNDDEF, ABORT_ILLTRP_ILL }, - { " - unknown exception", ABORT_TYPE_UNDDEF, ABORT_PRVOPC_ILL } + { " - instruction fetch", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - fetch packet", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - execute packet", ABORT_TYPE_UNDDEF, ABORT_OPCODE_ILL }, + { " - undefined instruction", ABORT_TYPE_UNDDEF, ABORT_OPCODE_ILL }, + { " - resource conflict", ABORT_TYPE_UNDDEF, ABORT_OPCODE_ILL }, + { " - resource access", ABORT_TYPE_UNDDEF, ABORT_PRVREG_ILL }, + { " - privilege", ABORT_TYPE_UNDDEF, ABORT_PRVOPC_ILL }, + { " - loops buffer", ABORT_TYPE_UNDDEF, ABORT_PRVOPC_ILL }, + { " - software exception", ABORT_TYPE_UNDDEF, ABORT_ILLTRP_ILL }, + { " - unknown exception", ABORT_TYPE_UNDDEF, ABORT_PRVOPC_ILL } }; /* @@ -136,163 +135,162 @@ static struct rt_exception_info iexcept_table[10] = { */ static int process_iexcept(struct rt_hw_exp_stack_register *regs) { - unsigned int iexcept_report = get_iexcept(); - unsigned int iexcept_num; + unsigned int iexcept_report = get_iexcept(); + unsigned int iexcept_num; - ack_exception(EXCEPT_TYPE_IXF); + ack_exception(EXCEPT_TYPE_IXF); - while(iexcept_report) { - iexcept_num = __ffs(iexcept_report); - iexcept_report &= ~(1 << iexcept_num); - set_iexcept(iexcept_report); + while(iexcept_report) { + iexcept_num = __ffs(iexcept_report); + iexcept_report &= ~(1 << iexcept_num); + set_iexcept(iexcept_report); - if (*(unsigned int *)regs->pc == BKPT_OPCODE) { - /* This is a breakpoint */ - struct rt_exception_info bkpt_exception = { " - undefined instruction", ABORT_TYPE_UNDDEF, ABORT_BRKPT_ILL }; - do_trap(&bkpt_exception, regs); - iexcept_report &= ~(0xFF); - set_iexcept(iexcept_report); - continue; - } - - do_trap(&iexcept_table[iexcept_num], regs); - } - return 0; + if (*(unsigned int *)regs->pc == BKPT_OPCODE) { + /* This is a breakpoint */ + struct rt_exception_info bkpt_exception = { " - undefined instruction", ABORT_TYPE_UNDDEF, ABORT_BRKPT_ILL }; + do_trap(&bkpt_exception, regs); + iexcept_report &= ~(0xFF); + set_iexcept(iexcept_report); + continue; + } + do_trap(&iexcept_table[iexcept_num], regs); + } + return 0; } static struct rt_exception_info except_table[128] = { - { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, - { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, - { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, - { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, - { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, - { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, - { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, - { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, - { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, - { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, - { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, - { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, - { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, - { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, - { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, - { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, - { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, - { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, - { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, - { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, - { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, - { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, - { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, - { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, - { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, - { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, - { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, - { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, - { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, - { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, - { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, - { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, - { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, - { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, - { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, - { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, - { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, - { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, - { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, - { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, - { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, - { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, - { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, - { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, - { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, - { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, - { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, - { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, - { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, - { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, - { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, - { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, - { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, - { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, - { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, - { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, - { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, - { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, - { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, - { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, - { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, - { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, - { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, - { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, - { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, - { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, - { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, - { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, - { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, - { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, - { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, - { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, - { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, - { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, - { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, - { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, - { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, - { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, - { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, - { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, - { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, - { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, - { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, - { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, - { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, - { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, - { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, - { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, - { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, - { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, - { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, - { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, - { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, - { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, - { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, - { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, - { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, - { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, - { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, - { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, - { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, - { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, - { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, - { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, - { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, - { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, - { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, - { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, - { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, - { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, - { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, - { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, - { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, - { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, - { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, - { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, - { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, - { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, - { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, - { " - CPU memory protection fault", ABORT_TYPE_MAP, ABORT_BUS_ACCERR }, - { " - CPU memory protection fault in L1P", ABORT_TYPE_MAP, ABORT_BUS_ACCERR }, - { " - DMA memory protection fault in L1P", ABORT_TYPE_MAP, ABORT_BUS_ACCERR }, - { " - CPU memory protection fault in L1D", ABORT_TYPE_MAP, ABORT_BUS_ACCERR }, - { " - DMA memory protection fault in L1D", ABORT_TYPE_MAP, ABORT_BUS_ACCERR }, - { " - CPU memory protection fault in L2", ABORT_TYPE_MAP, ABORT_BUS_ACCERR }, - { " - DMA memory protection fault in L2", ABORT_TYPE_MAP, ABORT_BUS_ACCERR }, - { " - EMC CPU memory protection fault", ABORT_TYPE_MAP, ABORT_BUS_ACCERR }, - { " - EMC bus error", ABORT_TYPE_MAP, ABORT_BUS_ADDRERR } + { " - CPU memory protection fault", ABORT_TYPE_MAP, ABORT_BUS_ACCERR }, + { " - CPU memory protection fault in L1P", ABORT_TYPE_MAP, ABORT_BUS_ACCERR }, + { " - DMA memory protection fault in L1P", ABORT_TYPE_MAP, ABORT_BUS_ACCERR }, + { " - CPU memory protection fault in L1D", ABORT_TYPE_MAP, ABORT_BUS_ACCERR }, + { " - DMA memory protection fault in L1D", ABORT_TYPE_MAP, ABORT_BUS_ACCERR }, + { " - CPU memory protection fault in L2", ABORT_TYPE_MAP, ABORT_BUS_ACCERR }, + { " - DMA memory protection fault in L2", ABORT_TYPE_MAP, ABORT_BUS_ACCERR }, + { " - EMC CPU memory protection fault", ABORT_TYPE_MAP, ABORT_BUS_ACCERR }, + { " - EMC bus error", ABORT_TYPE_MAP, ABORT_BUS_ADDRERR } }; /* @@ -300,22 +298,22 @@ static struct rt_exception_info except_table[128] = { */ static void process_except(struct rt_hw_exp_stack_register *regs) { - int except_num; - int bank = 0; - int i; + int except_num; + int bank = 0; + int i; - for (i = 0; i <= 3; i++) { - while (INTC_MEXPMASK[i]) { - __dint(); - except_num = __ffs(INTC_MEXPMASK[i]); - INTC_MEXPMASK[i] &= ~(1 << except_num); /* ack the external exception */ - __rint(); - do_trap(&except_table[except_num + (bank << 5)], regs); - } - bank++; - } + for (i = 0; i <= 3; i++) { + while (INTC_MEXPMASK[i]) { + __dint(); + except_num = __ffs(INTC_MEXPMASK[i]); + INTC_MEXPMASK[i] &= ~(1 << except_num); /* ack the external exception */ + __rint(); + do_trap(&except_table[except_num + (bank << 5)], regs); + } + bank++; + } - ack_exception(EXCEPT_TYPE_EXC); + ack_exception(EXCEPT_TYPE_EXC); } extern void hw_nmi_handler(struct rt_hw_exp_stack_register *regs); @@ -325,39 +323,39 @@ extern void hw_nmi_handler(struct rt_hw_exp_stack_register *regs); */ int rt_hw_process_exception(struct rt_hw_exp_stack_register *regs) { - int type; - int type_num; - int ie_num = 9; /* default is unknown exception */ + int type; + int type_num; + int ie_num = 9; /* default is unknown exception */ - while ((type = get_except_type()) != 0) { - type_num = __fls(type) - 1; + while ((type = get_except_type()) != 0) { + type_num = __fls(type) - 1; - switch(type_num) { - case EXCEPT_TYPE_NXF: /* NMI exception */ - ack_exception(EXCEPT_TYPE_NXF); /* clear exception */ - if (hw_nmi_handler != RT_NULL) - hw_nmi_handler(regs); - break; + switch(type_num) { + case EXCEPT_TYPE_NXF: /* NMI exception */ + ack_exception(EXCEPT_TYPE_NXF); /* clear exception */ + if (hw_nmi_handler != RT_NULL) + hw_nmi_handler(regs); + break; - case EXCEPT_TYPE_IXF: /* internal exception */ - if (process_iexcept(regs)) - return 1; - break; + case EXCEPT_TYPE_IXF: /* internal exception */ + if (process_iexcept(regs)) + return 1; + break; - case EXCEPT_TYPE_EXC: /* external exception */ - process_except(regs); - break; + case EXCEPT_TYPE_EXC: /* external exception */ + process_except(regs); + break; - case EXCEPT_TYPE_SXF: /* software exception */ - ie_num = 8; - ack_exception(type_num); - break; - default: /* clear exception */ - ack_exception(type_num); - do_trap(&iexcept_table[ie_num], regs); - break; - } - } - return 0; + case EXCEPT_TYPE_SXF: /* software exception */ + ie_num = 8; + ack_exception(type_num); + break; + default: /* clear exception */ + ack_exception(type_num); + do_trap(&iexcept_table[ie_num], regs); + break; + } + } + return 0; } From 4a2ce8bca5b3682a514de8b1a0499624ad6da1fc Mon Sep 17 00:00:00 2001 From: Huang bo Date: Thu, 18 Nov 2021 09:48:06 +0800 Subject: [PATCH 09/24] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E6=A0=BC=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- bsp/ti-tms320c6678/driver/drv_timer.c | 8 +++--- libcpu/ti-dsp/c6x/interrupt.c | 7 +++++- libcpu/ti-dsp/c6x/trap.c | 28 +++++++++++++-------- libcpu/ti-dsp/c6x/trap.h | 36 +++++++++++++-------------- 4 files changed, 45 insertions(+), 34 deletions(-) diff --git a/bsp/ti-tms320c6678/driver/drv_timer.c b/bsp/ti-tms320c6678/driver/drv_timer.c index a755689df4..30b2770f24 100644 --- a/bsp/ti-tms320c6678/driver/drv_timer.c +++ b/bsp/ti-tms320c6678/driver/drv_timer.c @@ -35,7 +35,7 @@ void rt_hw_systick_isr(void) void rt_hw_system_timer_init(void) { // initial system timer interrupt, map local timer interrupt to INT14 - gpCGEM_regs->INTMUX3=(CSL_GEM_TINTLN<INTMUX3 = (CSL_GEM_TINTLN<TOUTSEL = (DNUM*2)<= MAX_HANDLERS) + { return; + } } /** @@ -56,7 +57,9 @@ void rt_hw_interrupt_mask(int vector) void rt_hw_interrupt_umask(int vector) { if (vector < 0 || vector >= MAX_HANDLERS) + { return; + } } /** @@ -90,5 +93,7 @@ rt_isr_handler_t rt_hw_interrupt_install(int vector, rt_isr_handler_t handler, void rt_hw_interrupt_clear(int vector) { if (vector < 0 || vector >= MAX_HANDLERS) + { return; + } } diff --git a/libcpu/ti-dsp/c6x/trap.c b/libcpu/ti-dsp/c6x/trap.c index 7d4c063798..c7030c9bec 100644 --- a/libcpu/ti-dsp/c6x/trap.c +++ b/libcpu/ti-dsp/c6x/trap.c @@ -12,9 +12,8 @@ #include "c66xx.h" #include -#include - #include +#include #define RT_SYS_STACK_SIZE 4096 @@ -136,16 +135,18 @@ static struct rt_exception_info iexcept_table[10] = { static int process_iexcept(struct rt_hw_exp_stack_register *regs) { unsigned int iexcept_report = get_iexcept(); - unsigned int iexcept_num; + unsigned int iexcept_num = 0; ack_exception(EXCEPT_TYPE_IXF); - while(iexcept_report) { + while(iexcept_report) + { iexcept_num = __ffs(iexcept_report); iexcept_report &= ~(1 << iexcept_num); set_iexcept(iexcept_report); - if (*(unsigned int *)regs->pc == BKPT_OPCODE) { + if (*(unsigned int *)regs->pc == BKPT_OPCODE) + { /* This is a breakpoint */ struct rt_exception_info bkpt_exception = { " - undefined instruction", ABORT_TYPE_UNDDEF, ABORT_BRKPT_ILL }; do_trap(&bkpt_exception, regs); @@ -300,10 +301,12 @@ static void process_except(struct rt_hw_exp_stack_register *regs) { int except_num; int bank = 0; - int i; + int i = 0; - for (i = 0; i <= 3; i++) { - while (INTC_MEXPMASK[i]) { + for (i = 0; i <= 3; i++) + { + while (INTC_MEXPMASK[i]) + { __dint(); except_num = __ffs(INTC_MEXPMASK[i]); INTC_MEXPMASK[i] &= ~(1 << except_num); /* ack the external exception */ @@ -317,14 +320,13 @@ static void process_except(struct rt_hw_exp_stack_register *regs) } extern void hw_nmi_handler(struct rt_hw_exp_stack_register *regs); - /* * Main exception processing */ int rt_hw_process_exception(struct rt_hw_exp_stack_register *regs) { - int type; - int type_num; + int type = 0; + int type_num = 0; int ie_num = 9; /* default is unknown exception */ while ((type = get_except_type()) != 0) { @@ -334,12 +336,16 @@ int rt_hw_process_exception(struct rt_hw_exp_stack_register *regs) case EXCEPT_TYPE_NXF: /* NMI exception */ ack_exception(EXCEPT_TYPE_NXF); /* clear exception */ if (hw_nmi_handler != RT_NULL) + { hw_nmi_handler(regs); + } break; case EXCEPT_TYPE_IXF: /* internal exception */ if (process_iexcept(regs)) + { return 1; + } break; case EXCEPT_TYPE_EXC: /* external exception */ diff --git a/libcpu/ti-dsp/c6x/trap.h b/libcpu/ti-dsp/c6x/trap.h index 062acee768..9c8f52dd14 100644 --- a/libcpu/ti-dsp/c6x/trap.h +++ b/libcpu/ti-dsp/c6x/trap.h @@ -41,34 +41,34 @@ enum SYSTEM_TRAP_CODE { - ABORT_BUS_ADDRERR = 0, // bus address error - ABORT_BUS_ACCERR, // bus access permission error - ABORT_OPCODE_ILL, // illegal opcode - ABORT_PRVREG_ILL, // privilege register - ABORT_PRVOPC_ILL, // privileged opcode - ABORT_ILLTRP_ILL, // illegal trap - ABORT_BRKPT_ILL, // handling breakpoints + ABORT_BUS_ADDRERR = 0, // bus address error + ABORT_BUS_ACCERR, // bus access permission error + ABORT_OPCODE_ILL, // illegal opcode + ABORT_PRVREG_ILL, // privilege register + ABORT_PRVOPC_ILL, // privileged opcode + ABORT_ILLTRP_ILL, // illegal trap + ABORT_BRKPT_ILL, // handling breakpoints }; /* * abort types */ -#define ABORT_TYPE_BUS 0 // bus access abnormal -#define ABORT_TYPE_MAP 1 // page table mapping error -#define ABORT_TYPE_UNDDEF 0xff // undefined exception -#define ABORT_TYPE_FATAL 0xffffffff // fatal error +#define ABORT_TYPE_BUS 0 // bus access abnormal +#define ABORT_TYPE_MAP 1 // page table mapping error +#define ABORT_TYPE_UNDDEF 0xff // undefined exception +#define ABORT_TYPE_FATAL 0xffffffff // fatal error struct rt_exception_info { - char *kernel_str; - int type; - int code; + char *kernel_str; + int type; + int code; }; -#define BKPT_OPCODE 0x56454314 /* illegal opcode */ -#define INTC_MEXPMASK __SYSREGA(0x018000e0, unsigned int) +#define BKPT_OPCODE 0x56454314 /* illegal opcode */ +#define INTC_MEXPMASK __SYSREGA(0x018000e0, unsigned int) -#define __ffs(a) (_lmbd(1, _bitr(a))) -#define __fls(a) (!(a) ? 0 : (32 - _lmbd(1, (a)))) +#define __ffs(a) (_lmbd(1, _bitr(a))) +#define __fls(a) (!(a) ? 0 : (32 - _lmbd(1, (a)))) extern void rt_trap_init(void); From 17246ed77bad3e00941555e225dd35a754ba143c Mon Sep 17 00:00:00 2001 From: Huang bo Date: Thu, 18 Nov 2021 09:56:45 +0800 Subject: [PATCH 10/24] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E6=A0=BC=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- bsp/ti-tms320c6678/driver/drv_timer.c | 8 ++++---- libcpu/ti-dsp/c6x/trap.c | 7 ++++--- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/bsp/ti-tms320c6678/driver/drv_timer.c b/bsp/ti-tms320c6678/driver/drv_timer.c index 30b2770f24..9fe4e05fed 100644 --- a/bsp/ti-tms320c6678/driver/drv_timer.c +++ b/bsp/ti-tms320c6678/driver/drv_timer.c @@ -35,9 +35,9 @@ void rt_hw_systick_isr(void) void rt_hw_system_timer_init(void) { // initial system timer interrupt, map local timer interrupt to INT14 - gpCGEM_regs->INTMUX3 = (CSL_GEM_TINTLN<INTMUX3 = (CSL_GEM_TINTLN << CSL_CGEM_INTMUX3_INTSEL14_SHIFT); // enable CPU INT14 - CPU_interrupt_enable(1<<14); + CPU_interrupt_enable(1 << 14); return ; } @@ -52,12 +52,12 @@ void rt_hw_system_timer_start(void) Timer64_Config tmrCfg; // select output on TIMO0 from local timer. - gpBootCfgRegs->TOUTSEL = (DNUM*2)<TOUTSEL = (DNUM*2) << CSL_BOOTCFG_TOUTSEL_TOUTSEL0_SHIFT; // configure the timer to generate clocks and interrupts tmrCfg.timer_num = DNUM; tmrCfg.timerMode = TIMER_PERIODIC_CLOCK; - tmrCfg.period = (unsigned long long) RT_TICK_PER_SECOND*gDSP_Core_Speed_Hz/6000; + tmrCfg.period = (unsigned long long) RT_TICK_PER_SECOND * gDSP_Core_Speed_Hz / 6000; tmrCfg.reload_period = 0; // initial timer diff --git a/libcpu/ti-dsp/c6x/trap.c b/libcpu/ti-dsp/c6x/trap.c index c7030c9bec..634e486396 100644 --- a/libcpu/ti-dsp/c6x/trap.c +++ b/libcpu/ti-dsp/c6x/trap.c @@ -106,7 +106,6 @@ void show_regs(struct rt_hw_exp_stack_register *regs) regs->hw_register.a31, regs->hw_register.b31); } - void do_trap(struct rt_exception_info *except_info, struct rt_hw_exp_stack_register *regs) { rt_kprintf("Enter exception: %s\n", except_info->kernel_str); @@ -148,7 +147,9 @@ static int process_iexcept(struct rt_hw_exp_stack_register *regs) if (*(unsigned int *)regs->pc == BKPT_OPCODE) { /* This is a breakpoint */ - struct rt_exception_info bkpt_exception = { " - undefined instruction", ABORT_TYPE_UNDDEF, ABORT_BRKPT_ILL }; + struct rt_exception_info bkpt_exception = \ + { " - undefined instruction",\ + ABORT_TYPE_UNDDEF, ABORT_BRKPT_ILL }; do_trap(&bkpt_exception, regs); iexcept_report &= ~(0xFF); set_iexcept(iexcept_report); @@ -299,7 +300,7 @@ static struct rt_exception_info except_table[128] = { */ static void process_except(struct rt_hw_exp_stack_register *regs) { - int except_num; + int except_num = 0; int bank = 0; int i = 0; From c69cdadd69bdc2733b2774997c62006eaad4cce6 Mon Sep 17 00:00:00 2001 From: Huang bo Date: Thu, 18 Nov 2021 10:08:01 +0800 Subject: [PATCH 11/24] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E6=A0=BC=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- libcpu/ti-dsp/c6x/interrupt.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/libcpu/ti-dsp/c6x/interrupt.c b/libcpu/ti-dsp/c6x/interrupt.c index 6479da02f2..1bfc19cbdd 100644 --- a/libcpu/ti-dsp/c6x/interrupt.c +++ b/libcpu/ti-dsp/c6x/interrupt.c @@ -45,9 +45,9 @@ void rt_hw_interrupt_init(void) void rt_hw_interrupt_mask(int vector) { if (vector < 0 || vector >= MAX_HANDLERS) - { + { return; - } + } } /** @@ -57,9 +57,9 @@ void rt_hw_interrupt_mask(int vector) void rt_hw_interrupt_umask(int vector) { if (vector < 0 || vector >= MAX_HANDLERS) - { + { return; - } + } } /** @@ -93,7 +93,7 @@ rt_isr_handler_t rt_hw_interrupt_install(int vector, rt_isr_handler_t handler, void rt_hw_interrupt_clear(int vector) { if (vector < 0 || vector >= MAX_HANDLERS) - { - return; - } + { + return; + } } From 4a779f5131dea2ebcf95cc275df3ab23850ac6c0 Mon Sep 17 00:00:00 2001 From: Huang bo Date: Tue, 23 Nov 2021 16:28:44 +0800 Subject: [PATCH 12/24] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E4=BD=BF=E7=94=A8C?= =?UTF-8?q?=E8=AF=AD=E8=A8=80=E6=9E=84=E5=BB=BA=E4=BB=BB=E5=8A=A1=E6=A0=88?= =?UTF-8?q?=E5=B8=A7=EF=BC=8C=E6=B8=85=E9=99=A4fls=E5=92=8Cffs=E5=AF=B9=E6=96=87=E4=BB=B6=E7=9A=84=E4=BE=9D=E8=B5=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- libcpu/ti-dsp/c6x/c66xx.h | 18 +++-- libcpu/ti-dsp/c6x/context.asm | 34 ++++++++++ libcpu/ti-dsp/c6x/cpuport.c | 2 +- libcpu/ti-dsp/c6x/interrupt.c | 2 +- libcpu/ti-dsp/c6x/intexc.asm | 4 +- libcpu/ti-dsp/c6x/stack.asm | 107 ------------------------------ libcpu/ti-dsp/c6x/stack.c | 120 ++++++++++++++++++++++++++++++++++ libcpu/ti-dsp/c6x/trap.c | 27 ++++---- libcpu/ti-dsp/c6x/trap.h | 47 +++++++++++-- 9 files changed, 228 insertions(+), 133 deletions(-) delete mode 100644 libcpu/ti-dsp/c6x/stack.asm create mode 100644 libcpu/ti-dsp/c6x/stack.c diff --git a/libcpu/ti-dsp/c6x/c66xx.h b/libcpu/ti-dsp/c6x/c66xx.h index ea204907d8..903edbfaf1 100644 --- a/libcpu/ti-dsp/c6x/c66xx.h +++ b/libcpu/ti-dsp/c6x/c66xx.h @@ -11,7 +11,15 @@ #ifndef __C66XX_H__ #define __C66XX_H__ -#include +extern cregister volatile unsigned int IERR; /* Internal Exception Report Register */ +extern cregister volatile unsigned int ECR; /* Exception Clear Register */ +extern cregister volatile unsigned int EFR; /* Exception Flag Register */ +extern cregister volatile unsigned int TSR; /* Task State Register */ +extern cregister volatile unsigned int ITSR; /* Interrupt Task State Register */ +extern cregister volatile unsigned int NTSR; /* NMI/exception Task State Register */ +extern cregister volatile unsigned int TSCL; /* Time Stamp Counter Register - Low Half */ +extern cregister volatile unsigned int TSCH; /* Time Stamp Counter Register - High Half */ +extern cregister volatile unsigned int DNUM; /* Core number */ #ifdef _BIG_ENDIAN #define RT_REG_PAIR(odd, even) unsigned long odd; unsigned long even @@ -37,7 +45,7 @@ struct rt_hw_register RT_REG_PAIR(b9, b8); RT_REG_PAIR(b11, b10); RT_REG_PAIR(b13, b12); - + RT_REG_PAIR(a17, a16); RT_REG_PAIR(a19, a18); RT_REG_PAIR(a21, a20); @@ -58,14 +66,14 @@ struct rt_hw_register RT_REG_PAIR(a15, a14); RT_REG_PAIR(sp, dp); }; - -struct rt_hw_exp_stack_register + +typedef struct rt_hw_exp_stack_register { RT_REG_PAIR(tsr, orig_a4); RT_REG_PAIR(rilc, ilc); RT_REG_PAIR(pc, csr); struct rt_hw_register hw_register; -}; +} rt_hw_thread_stack_register; #define __dint() asm(" DINT") #define __rint() asm(" RINT") diff --git a/libcpu/ti-dsp/c6x/context.asm b/libcpu/ti-dsp/c6x/context.asm index b3146d1eb3..2a57e9414d 100644 --- a/libcpu/ti-dsp/c6x/context.asm +++ b/libcpu/ti-dsp/c6x/context.asm @@ -79,6 +79,40 @@ rt_hw_interrupt_enable: NOP 5 ;} +;----------------------------------------------------------- +; rt_uint32_t rt_hw_get_current_dp(void) +;----------------------------------------------------------- + .global rt_hw_get_current_dp +rt_hw_get_current_dp: +;{ + B B3 + MV B14, A4 + NOP 4 +;} + +;----------------------------------------------------------- +; rt_int32_t __fls(rt_int32_t val) +;----------------------------------------------------------- + .global __fls +__fls: +;{ + B B3 + LMBD .L1 1,A4,A4 + NOP 4 +;} + +;----------------------------------------------------------- +; rt_int32_t __ffs(rt_int32_t val) +;----------------------------------------------------------- + .global __ffs +__ffs: +;{ + BITR .M1 A4,A4 + B B3 + LMBD .L1 1,A4,A4 + NOP 4 +;} + ; ;----------------------------------------------------------- ; diff --git a/libcpu/ti-dsp/c6x/cpuport.c b/libcpu/ti-dsp/c6x/cpuport.c index 367b884a60..3f755a5c7c 100644 --- a/libcpu/ti-dsp/c6x/cpuport.c +++ b/libcpu/ti-dsp/c6x/cpuport.c @@ -158,7 +158,7 @@ void hw_int11_handler(void) -----------------------------------------------------------------------------*/ void hw_int12_handler(void) { - + } /*------------ hw_int13_handler() function ------------------------------------ diff --git a/libcpu/ti-dsp/c6x/interrupt.c b/libcpu/ti-dsp/c6x/interrupt.c index 1bfc19cbdd..2be2f88313 100644 --- a/libcpu/ti-dsp/c6x/interrupt.c +++ b/libcpu/ti-dsp/c6x/interrupt.c @@ -94,6 +94,6 @@ void rt_hw_interrupt_clear(int vector) { if (vector < 0 || vector >= MAX_HANDLERS) { - return; + return; } } diff --git a/libcpu/ti-dsp/c6x/intexc.asm b/libcpu/ti-dsp/c6x/intexc.asm index 4485c6579c..2490977331 100644 --- a/libcpu/ti-dsp/c6x/intexc.asm +++ b/libcpu/ti-dsp/c6x/intexc.asm @@ -81,7 +81,9 @@ RT_INTERRUPT_ENTRY .macro .endm RT_CALL_INT .macro __isr - CALLP __isr,B3 + B __isr + ADDKPC $1 ,B3,4 +$1: B .S1 rt_interrupt_context_restore NOP 5 .endm diff --git a/libcpu/ti-dsp/c6x/stack.asm b/libcpu/ti-dsp/c6x/stack.asm deleted file mode 100644 index f9b31dec93..0000000000 --- a/libcpu/ti-dsp/c6x/stack.asm +++ /dev/null @@ -1,107 +0,0 @@ -; -; Copyright (c) 2021, Shenzhen Academy of Aerospace Technology -; -; SPDX-License-Identifier: Apache-2.0 -; -; Change Logs: -; Date Author Notes -; 2021-11-16 Dystopia the first version -; - -;----------------------------------------------------------- -; build thread stack for C6000 DSP -;----------------------------------------------------------- - -;----------------------------------------------------------- -; macro definition -;----------------------------------------------------------- -ADDRESS_MSK .set 0xFFFFFFF0 - -; -;----------------------------------------------------------- -; - - .sect ".text" -; -;----------------------------------------------------------- -; - -; -; rt_uint8_t *rt_hw_stack_init(void *tentry, void *parameter, rt_uint8_t *stack_addr, void *texit) -; tentry --> A4 -; parameter --> B4 -; stack_addr --> A6 -; texit --> B6 -;{ - .global rt_hw_stack_init -rt_hw_stack_init: - SUB A6,1,B1 ; - MVKL .S1 ADDRESS_MSK,A1 ; - MVKH .S1 ADDRESS_MSK,A1 ; Build address mask - MVC .S2 CSR,B0 ; - AND -2,B0,B0 ; Clear GIE bit - OR 2,B0,B0 ; Set PGIE bit for interrupt return - AND A1,B1,B1 ; Ensure alignment -; -; Actually build the stack frame. -; - MV .S1 B1,A3 - MV .S1 B14,A2 - STDW .D2T1 A3:A2,*--B1[1] ; Initial B15:B14 - SUBAW .D2 B1,2,B1 - ZERO A2 - ZERO A3 ; Clear value - STDW .D2T1 A3:A2,*B1--[1] ; Initial A15:A14 - STDW .D2T1 A3:A2,*B1--[1] ; Initial A13:A12 - STDW .D2T1 A3:A2,*B1--[1] ; Initial A11:A10 - STDW .D2T1 A3:A2,*B1--[1] ; Initial A9:A8 - STDW .D2T1 A3:A2,*B1--[1] ; Initial A7:A6 - MV .S1 B4,A2 - STDW .D2T1 A3:A2,*B1--[1] ; Initial A5:A4 - ZERO A2 - STDW .D2T1 A3:A2,*B1--[1] ; Initial A3:A2 - STDW .D2T1 A3:A2,*B1--[1] ; Initial A1:A0 - - STDW .D2T1 A3:A2,*B1--[1] ; Initial A31:A30 - STDW .D2T1 A3:A2,*B1--[1] ; Initial A29:A28 - STDW .D2T1 A3:A2,*B1--[1] ; Initial A27:A26 - STDW .D2T1 A3:A2,*B1--[1] ; Initial A25:A24 - STDW .D2T1 A3:A2,*B1--[1] ; Initial A23:A22 - STDW .D2T1 A3:A2,*B1--[1] ; Initial A21:A20 - STDW .D2T1 A3:A2,*B1--[1] ; Initial A19:A18 - STDW .D2T1 A3:A2,*B1--[1] ; Initial A17:A16 - - STDW .D2T1 A3:A2,*B1--[1] ; Initial B13:B12 - STDW .D2T1 A3:A2,*B1--[1] ; Initial B11:B10 - STDW .D2T1 A3:A2,*B1--[1] ; Initial B9:B8 - STDW .D2T1 A3:A2,*B1--[1] ; Initial B7:B6 - STDW .D2T1 A3:A2,*B1--[1] ; Initial B5:B4 - MV .S1 B6,A3 - STDW .D2T1 A3:A2,*B1--[1] ; Initial B3:B2 - ZERO A3 - STDW .D2T1 A3:A2,*B1--[1] ; Initial B1:B0 - - STDW .D2T1 A3:A2,*B1--[1] ; Initial B31:B30 - STDW .D2T1 A3:A2,*B1--[1] ; Initial B29:B28 - STDW .D2T1 A3:A2,*B1--[1] ; Initial B27:B26 - STDW .D2T1 A3:A2,*B1--[1] ; Initial B25:B24 - STDW .D2T1 A3:A2,*B1--[1] ; Initial B23:B22 - STDW .D2T1 A3:A2,*B1--[1] ; Initial B21:B20 - STDW .D2T1 A3:A2,*B1--[1] ; Initial B19:B18 - STDW .D2T1 A3:A2,*B1--[1] ; Initial B17:B16 - - MV .S1 A4,A3 - MV .S1 B0,A2 - STDW .D2T1 A3:A2,*B1--[1] ; Initial PC:CSR - - ZERO A2 - ZERO A3 - STDW .D2T1 A3:A2,*B1--[1] ; Initial ILC:RILC - B B3 - MVKL .S2 0x3,B0 - MV .S1 B0,A3 - MVKL .S1 1,A2 - STDW .D2T1 A3:A2,*B1--[1] ; Initial TSR:stack type - MV .S1 B1,A4 ; Save to TCB -;} - .end diff --git a/libcpu/ti-dsp/c6x/stack.c b/libcpu/ti-dsp/c6x/stack.c new file mode 100644 index 0000000000..3fe3377a1c --- /dev/null +++ b/libcpu/ti-dsp/c6x/stack.c @@ -0,0 +1,120 @@ +/* + * Copyright (c) 2021, Shenzhen Academy of Aerospace Technology + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2021-11-16 Dystopia the first version + */ + +#include +#include + +extern rt_uint32_t rt_hw_get_current_dp(void); + +/** + * @addtogroup C66xx + */ +/*@{*/ + +/** + * This function will initialize thread stack + * + * @param tentry the entry of thread + * @param parameter the parameter of entry + * @param stack_addr the beginning stack address + * @param texit the function will be called when thread exit + * + * @return stack address + */ +rt_uint8_t *rt_hw_stack_init(void *tentry, void *parameter, + rt_uint8_t *stack_addr, void *texit) +{ + rt_hw_thread_stack_register *thread_context; + rt_uint32_t stk; + + stack_addr += sizeof(rt_uint32_t); + stack_addr = (rt_uint8_t *)RT_ALIGN_DOWN((rt_uint32_t)stack_addr, 8); + stk = (rt_uint32_t)stack_addr; + thread_context = (rt_hw_thread_stack_register *)(stk - sizeof(rt_hw_thread_stack_register)); + + thread_context->pc = (rt_uint32_t)tentry; + thread_context->csr = 0x0103; + thread_context->tsr = 0x3; + thread_context->orig_a4 = 1; + thread_context->ilc = 0; + thread_context->rilc = 0; + + thread_context->hw_register.b17 = 0xB17; + thread_context->hw_register.b16 = 0xB16; + thread_context->hw_register.b19 = 0xB19; + thread_context->hw_register.b18 = 0xB18; + thread_context->hw_register.b21 = 0xB21; + thread_context->hw_register.b20 = 0xB20; + thread_context->hw_register.b23 = 0xB23; + thread_context->hw_register.b22 = 0xB22; + thread_context->hw_register.b25 = 0xB25; + thread_context->hw_register.b24 = 0xB24; + thread_context->hw_register.b27 = 0xB27; + thread_context->hw_register.b26 = 0xB26; + thread_context->hw_register.b29 = 0xB29; + thread_context->hw_register.b28 = 0xB28; + thread_context->hw_register.b31 = 0xB31; + thread_context->hw_register.b30 = 0xB30; + + thread_context->hw_register.b1 = 0xB01; + thread_context->hw_register.b0 = 0xB00; + thread_context->hw_register.b3 = (rt_uint32_t)texit; + thread_context->hw_register.b2 = 0xB02; + thread_context->hw_register.b5 = 0xB05; + thread_context->hw_register.b4 = 0xB04; + thread_context->hw_register.b7 = 0xB07; + thread_context->hw_register.b6 = 0xB06; + thread_context->hw_register.b9 = 0xB09; + thread_context->hw_register.b8 = 0xB08; + thread_context->hw_register.b11 = 0xB11; + thread_context->hw_register.b10 = 0xB10; + thread_context->hw_register.b13 = 0xB13; + thread_context->hw_register.b12 = 0xB12; + + thread_context->hw_register.a17 = 0xA17; + thread_context->hw_register.a16 = 0xA16; + thread_context->hw_register.a19 = 0xA19; + thread_context->hw_register.a18 = 0xA18; + thread_context->hw_register.a21 = 0xA21; + thread_context->hw_register.a20 = 0xA20; + thread_context->hw_register.a23 = 0xA23; + thread_context->hw_register.a22 = 0xA22; + thread_context->hw_register.a25 = 0xA25; + thread_context->hw_register.a24 = 0xA24; + thread_context->hw_register.a27 = 0xA27; + thread_context->hw_register.a26 = 0xA26; + thread_context->hw_register.a29 = 0xA29; + thread_context->hw_register.a28 = 0xA28; + thread_context->hw_register.a31 = 0xA31; + thread_context->hw_register.a30 = 0xA30; + + thread_context->hw_register.a1 = 0xA01; + thread_context->hw_register.a0 = 0xA00; + thread_context->hw_register.a3 = 0xA03; + thread_context->hw_register.a2 = 0xA02; + thread_context->hw_register.a5 = 0xA05; + thread_context->hw_register.a4 = (rt_uint32_t)parameter; + thread_context->hw_register.a7 = 0xA07; + thread_context->hw_register.a6 = 0xA06; + thread_context->hw_register.a9 = 0xA09; + thread_context->hw_register.a8 = 0xA08; + thread_context->hw_register.a11 = 0xA11; + thread_context->hw_register.a10 = 0xA10; + thread_context->hw_register.a13 = 0xA13; + thread_context->hw_register.a12 = 0xA12; + + thread_context->hw_register.a15 = 0xA15; + thread_context->hw_register.a14 = 0xA14; + thread_context->hw_register.dp = rt_hw_get_current_dp(); + thread_context->hw_register.sp = (rt_uint32_t)stk; + + /* return task's current stack address */ + return (rt_uint8_t *)thread_context - 8; +} diff --git a/libcpu/ti-dsp/c6x/trap.c b/libcpu/ti-dsp/c6x/trap.c index 634e486396..9f8f80d5ed 100644 --- a/libcpu/ti-dsp/c6x/trap.c +++ b/libcpu/ti-dsp/c6x/trap.c @@ -17,7 +17,6 @@ #define RT_SYS_STACK_SIZE 4096 -extern void rt_hw_enable_exception(void); rt_uint8_t rt_system_stack[RT_SYS_STACK_SIZE]; rt_uint8_t *rt_system_stack_top; @@ -117,14 +116,14 @@ void do_trap(struct rt_exception_info *except_info, struct rt_hw_exp_stack_regis static struct rt_exception_info iexcept_table[10] = { { " - instruction fetch", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, - { " - fetch packet", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, - { " - execute packet", ABORT_TYPE_UNDDEF, ABORT_OPCODE_ILL }, + { " - fetch packet", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, + { " - execute packet", ABORT_TYPE_UNDDEF, ABORT_OPCODE_ILL }, { " - undefined instruction", ABORT_TYPE_UNDDEF, ABORT_OPCODE_ILL }, { " - resource conflict", ABORT_TYPE_UNDDEF, ABORT_OPCODE_ILL }, - { " - resource access", ABORT_TYPE_UNDDEF, ABORT_PRVREG_ILL }, + { " - resource access", ABORT_TYPE_UNDDEF, ABORT_PRVREG_ILL }, { " - privilege", ABORT_TYPE_UNDDEF, ABORT_PRVOPC_ILL }, - { " - loops buffer", ABORT_TYPE_UNDDEF, ABORT_PRVOPC_ILL }, - { " - software exception", ABORT_TYPE_UNDDEF, ABORT_ILLTRP_ILL }, + { " - loops buffer", ABORT_TYPE_UNDDEF, ABORT_PRVOPC_ILL }, + { " - software exception", ABORT_TYPE_UNDDEF, ABORT_ILLTRP_ILL }, { " - unknown exception", ABORT_TYPE_UNDDEF, ABORT_PRVOPC_ILL } }; @@ -140,7 +139,7 @@ static int process_iexcept(struct rt_hw_exp_stack_register *regs) while(iexcept_report) { - iexcept_num = __ffs(iexcept_report); + iexcept_num = ffs(iexcept_report); iexcept_report &= ~(1 << iexcept_num); set_iexcept(iexcept_report); @@ -160,7 +159,7 @@ static int process_iexcept(struct rt_hw_exp_stack_register *regs) return 0; } -static struct rt_exception_info except_table[128] = { +static struct rt_exception_info eexcept_table[128] = { { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, { " - external exception", ABORT_TYPE_BUS, ABORT_BUS_ADDRERR }, @@ -298,7 +297,7 @@ static struct rt_exception_info except_table[128] = { /* * Process an external exception (maskable) */ -static void process_except(struct rt_hw_exp_stack_register *regs) +static void process_eexcept(struct rt_hw_exp_stack_register *regs) { int except_num = 0; int bank = 0; @@ -309,10 +308,10 @@ static void process_except(struct rt_hw_exp_stack_register *regs) while (INTC_MEXPMASK[i]) { __dint(); - except_num = __ffs(INTC_MEXPMASK[i]); + except_num = ffs(INTC_MEXPMASK[i]); INTC_MEXPMASK[i] &= ~(1 << except_num); /* ack the external exception */ __rint(); - do_trap(&except_table[except_num + (bank << 5)], regs); + do_trap(&eexcept_table[except_num + (bank << 5)], regs); } bank++; } @@ -331,11 +330,11 @@ int rt_hw_process_exception(struct rt_hw_exp_stack_register *regs) int ie_num = 9; /* default is unknown exception */ while ((type = get_except_type()) != 0) { - type_num = __fls(type) - 1; + type_num = fls(type) - 1; switch(type_num) { case EXCEPT_TYPE_NXF: /* NMI exception */ - ack_exception(EXCEPT_TYPE_NXF); /* clear exception */ + ack_exception(EXCEPT_TYPE_NXF); /* clear exception */ if (hw_nmi_handler != RT_NULL) { hw_nmi_handler(regs); @@ -350,7 +349,7 @@ int rt_hw_process_exception(struct rt_hw_exp_stack_register *regs) break; case EXCEPT_TYPE_EXC: /* external exception */ - process_except(regs); + process_eexcept(regs); break; case EXCEPT_TYPE_SXF: /* software exception */ diff --git a/libcpu/ti-dsp/c6x/trap.h b/libcpu/ti-dsp/c6x/trap.h index 9c8f52dd14..12734df4a7 100644 --- a/libcpu/ti-dsp/c6x/trap.h +++ b/libcpu/ti-dsp/c6x/trap.h @@ -67,10 +67,49 @@ struct rt_exception_info { #define BKPT_OPCODE 0x56454314 /* illegal opcode */ #define INTC_MEXPMASK __SYSREGA(0x018000e0, unsigned int) -#define __ffs(a) (_lmbd(1, _bitr(a))) -#define __fls(a) (!(a) ? 0 : (32 - _lmbd(1, (a)))) - extern void rt_trap_init(void); +extern void rt_hw_enable_exception(void); +extern int __fls(int val); +extern int __ffs(int val); + +/* + * ffz - find first zero in word. + * @word: The word to search + * + * Undefined if no zero exists, so code should check against ~0UL first. + */ +#define ffz(x) __ffs(~(x)) + +/** + * fls - find last (most-significant) bit set + * @x: the word to search + * + * This is defined the same way as ffs. + * Note fls(0) = 0, fls(1) = 1, fls(0x80000000) = 32. + */ +static inline int fls(int x) +{ + if (!x) + return 0; + + return 32 - __fls(x); +} + +/** + * ffs - find first bit set + * @x: the word to search + * + * This is defined the same way as + * the libc and compiler builtin ffs routines, therefore + * differs in spirit from the above ffz (man ffs). + * Note ffs(0) = 0, ffs(1) = 1, ffs(0x80000000) = 32. + */ +static inline int ffs(int x) +{ + if (!x) + return 0; + + return __ffs(x) + 1; +} #endif /* __TRAP_H__ */ - From c37fcb6049de1ba0c39265a261cc07fad78e6cf6 Mon Sep 17 00:00:00 2001 From: Huang bo Date: Wed, 15 Dec 2021 09:17:25 +0800 Subject: [PATCH 13/24] =?UTF-8?q?=E4=BF=AE=E6=94=B9bsp=20tms320c6678?= =?UTF-8?q?=E5=B7=A5=E7=A8=8B=EF=BC=8C=E5=B9=B6=E6=B5=8B=E8=AF=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- bsp/ti-tms320c6678/.cproject | 142 +- bsp/ti-tms320c6678/.project | 70 +- .../org.eclipse.core.resources.prefs | 10 - bsp/ti-tms320c6678/applications/main.c | 1 - bsp/ti-tms320c6678/common/KeyStone_common.c | 4355 +++++++++++++++++ bsp/ti-tms320c6678/common/KeyStone_common.h | 1090 +++++ bsp/ti-tms320c6678/readme.txt | 7 +- libcpu/ti-dsp/c6x/context.asm | 9 +- libcpu/ti-dsp/c6x/contextinc.asm | 5 + libcpu/ti-dsp/c6x/interrupt.c | 2 +- libcpu/ti-dsp/c6x/intexc.asm | 8 - libcpu/ti-dsp/c6x/stack.c | 4 +- libcpu/ti-dsp/c6x/trap.h | 6 +- 13 files changed, 5567 insertions(+), 142 deletions(-) delete mode 100644 bsp/ti-tms320c6678/.settings/org.eclipse.core.resources.prefs create mode 100644 bsp/ti-tms320c6678/common/KeyStone_common.c create mode 100644 bsp/ti-tms320c6678/common/KeyStone_common.h diff --git a/bsp/ti-tms320c6678/.cproject b/bsp/ti-tms320c6678/.cproject index aef3a8c240..0c4124a28d 100644 --- a/bsp/ti-tms320c6678/.cproject +++ b/bsp/ti-tms320c6678/.cproject @@ -3,8 +3,8 @@ - - + + @@ -14,10 +14,10 @@ - - - - - - + + @@ -89,10 +87,10 @@ - - - - - + diff --git a/bsp/ti-tms320c6678/.project b/bsp/ti-tms320c6678/.project index d1c8afd3a3..a0c5dddf40 100644 --- a/bsp/ti-tms320c6678/.project +++ b/bsp/ti-tms320c6678/.project @@ -1,6 +1,6 @@ - ti-c6678 + ti-tms320c6678 @@ -25,130 +25,130 @@ org.eclipse.cdt.managedbuilder.core.ScannerConfigNature - - SConscript - 1 - PARENT-2-PROJECT_LOC/src/SConscript - clock.c 1 - PARENT-2-PROJECT_LOC/src/clock.c + PARENT-2-PROJECT_LOC/git-source/rt-thread/src/clock.c components.c 1 - PARENT-2-PROJECT_LOC/src/components.c + PARENT-2-PROJECT_LOC/git-source/rt-thread/src/components.c context.asm 1 - PARENT-2-PROJECT_LOC/libcpu/ti-dsp/c6x/context.asm + PARENT-2-PROJECT_LOC/git-source/rt-thread/libcpu/ti-dsp/c6x/context.asm + + + contextinc.asm + 1 + PARENT-2-PROJECT_LOC/git-source/rt-thread/libcpu/ti-dsp/c6x/contextinc.asm cpu.c 1 - PARENT-2-PROJECT_LOC/src/cpu.c + PARENT-2-PROJECT_LOC/git-source/rt-thread/src/cpu.c cpuport.c 1 - PARENT-2-PROJECT_LOC/libcpu/ti-dsp/c6x/cpuport.c + PARENT-2-PROJECT_LOC/git-source/rt-thread/libcpu/ti-dsp/c6x/cpuport.c device.c 1 - PARENT-2-PROJECT_LOC/src/device.c + PARENT-2-PROJECT_LOC/git-source/rt-thread/src/device.c idle.c 1 - PARENT-2-PROJECT_LOC/src/idle.c - - - inct.asm - 1 - PARENT-2-PROJECT_LOC/libcpu/ti-dsp/c6x/inct.asm + PARENT-2-PROJECT_LOC/git-source/rt-thread/src/idle.c interrupt.c 1 - PARENT-2-PROJECT_LOC/libcpu/ti-dsp/c6x/interrupt.c + PARENT-2-PROJECT_LOC/git-source/rt-thread/libcpu/ti-dsp/c6x/interrupt.c + + + intexc.asm + 1 + PARENT-2-PROJECT_LOC/git-source/rt-thread/libcpu/ti-dsp/c6x/intexc.asm ipc.c 1 - PARENT-2-PROJECT_LOC/src/ipc.c + PARENT-2-PROJECT_LOC/git-source/rt-thread/src/ipc.c irq.c 1 - PARENT-2-PROJECT_LOC/src/irq.c + PARENT-2-PROJECT_LOC/git-source/rt-thread/src/irq.c kservice.c 1 - PARENT-2-PROJECT_LOC/src/kservice.c + PARENT-2-PROJECT_LOC/git-source/rt-thread/src/kservice.c mem.c 1 - PARENT-2-PROJECT_LOC/src/mem.c + PARENT-2-PROJECT_LOC/git-source/rt-thread/src/mem.c memheap.c 1 - PARENT-2-PROJECT_LOC/src/memheap.c + PARENT-2-PROJECT_LOC/git-source/rt-thread/src/memheap.c mempool.c 1 - PARENT-2-PROJECT_LOC/src/mempool.c + PARENT-2-PROJECT_LOC/git-source/rt-thread/src/mempool.c object.c 1 - PARENT-2-PROJECT_LOC/src/object.c + PARENT-2-PROJECT_LOC/git-source/rt-thread/src/object.c scheduler.c 1 - PARENT-2-PROJECT_LOC/src/scheduler.c + PARENT-2-PROJECT_LOC/git-source/rt-thread/src/scheduler.c signal.c 1 - PARENT-2-PROJECT_LOC/src/signal.c + PARENT-2-PROJECT_LOC/git-source/rt-thread/src/signal.c slab.c 1 - PARENT-2-PROJECT_LOC/src/slab.c + PARENT-2-PROJECT_LOC/git-source/rt-thread/src/slab.c - stack.asm + stack.c 1 - PARENT-2-PROJECT_LOC/libcpu/ti-dsp/c6x/stack.asm + PARENT-2-PROJECT_LOC/git-source/rt-thread/libcpu/ti-dsp/c6x/stack.c thread.c 1 - PARENT-2-PROJECT_LOC/src/thread.c + PARENT-2-PROJECT_LOC/git-source/rt-thread/src/thread.c timer.c 1 - PARENT-2-PROJECT_LOC/src/timer.c + PARENT-2-PROJECT_LOC/git-source/rt-thread/src/timer.c trap.c 1 - PARENT-2-PROJECT_LOC/libcpu/ti-dsp/c6x/trap.c + PARENT-2-PROJECT_LOC/git-source/rt-thread/libcpu/ti-dsp/c6x/trap.c vector.asm 1 - PARENT-2-PROJECT_LOC/libcpu/ti-dsp/c6x/vector.asm + PARENT-2-PROJECT_LOC/git-source/rt-thread/libcpu/ti-dsp/c6x/vector.asm diff --git a/bsp/ti-tms320c6678/.settings/org.eclipse.core.resources.prefs b/bsp/ti-tms320c6678/.settings/org.eclipse.core.resources.prefs deleted file mode 100644 index 83b10321a8..0000000000 --- a/bsp/ti-tms320c6678/.settings/org.eclipse.core.resources.prefs +++ /dev/null @@ -1,10 +0,0 @@ -eclipse.preferences.version=1 -encoding//Debug/applications/subdir_rules.mk=UTF-8 -encoding//Debug/applications/subdir_vars.mk=UTF-8 -encoding//Debug/driver/subdir_rules.mk=UTF-8 -encoding//Debug/driver/subdir_vars.mk=UTF-8 -encoding//Debug/makefile=UTF-8 -encoding//Debug/objects.mk=UTF-8 -encoding//Debug/sources.mk=UTF-8 -encoding//Debug/subdir_rules.mk=UTF-8 -encoding//Debug/subdir_vars.mk=UTF-8 diff --git a/bsp/ti-tms320c6678/applications/main.c b/bsp/ti-tms320c6678/applications/main.c index d29fd00a4f..aab374fa63 100644 --- a/bsp/ti-tms320c6678/applications/main.c +++ b/bsp/ti-tms320c6678/applications/main.c @@ -16,7 +16,6 @@ void rt_init_thread_entry(void *parameter) { rt_kprintf("hello rt-thread\n"); - return 0; } int rt_application_init(void) diff --git a/bsp/ti-tms320c6678/common/KeyStone_common.c b/bsp/ti-tms320c6678/common/KeyStone_common.c new file mode 100644 index 0000000000..bfa6fbac3c --- /dev/null +++ b/bsp/ti-tms320c6678/common/KeyStone_common.c @@ -0,0 +1,4355 @@ +/****************************************************************************** + + Copyright (C), 2001-2012, Texas Instrument. + + ****************************************************************************** + File Name : KeyStone_common.c + Version : Initial Draft + Author : Brighton Feng + Created : 2010-12-12 + Last Modified : + Description : KeyStone common miscellaneous functions and definitions + History : + 1.Date : 2010-12-12 + Author : Brighton Feng + Modification: Created file + + 2.Date : 2012-10-6 + Author : Brighton Feng + Modification : Add memory protection and EDC configuration + + 3.Date : 2014-12-8 + Author : Brighton Feng + Modification : Add common device, CPU, interrupt initialization functions. + Print device information including device type, speed grade, + boot mode, required voltage, ID�� + Add EDMA enable/disable functions. + To support square wave generation by timer. +******************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include "CSL_msmc.h" +#include "CSL_msmcAux.h" +#include "KeyStone_common.h" + +/*----------------------------------------------* + * external variables * + *----------------------------------------------*/ + +/*----------------------------------------------* + * external routine prototypes * + *----------------------------------------------*/ + +/*----------------------------------------------* + * internal routine prototypes * + *----------------------------------------------*/ + +/*----------------------------------------------* + * project-wide global variables * + *----------------------------------------------*/ +CSL_XmcRegs * gpXMC_regs = (CSL_XmcRegs *) CSL_XMC_CONFIG_REGS; +CSL_CgemRegs * gpCGEM_regs = (CSL_CgemRegs *)CSL_CGEM0_5_REG_BASE_ADDRESS_REGS; +CSL_BootcfgRegs * gpBootCfgRegs = (CSL_BootcfgRegs *)CSL_BOOT_CFG_REGS; +CSL_PllcRegs * gpPLLC_regs = (CSL_PllcRegs * )CSL_PLL_CONTROLLER_REGS; +CSL_PscRegs * gpPSC_regs = (CSL_PscRegs *)CSL_PSC_REGS; +CSL_MsmcRegs * gpMSMC_regs = (CSL_MsmcRegs *)CSL_MSMC_CONFIG_REGS; +CSL_GpioRegs * gpGPIO_regs= (CSL_GpioRegs * )CSL_GPIO_REGS; + +CSL_CPINTCRegs* gpCIC0_regs = (CSL_CPINTCRegs*)CSL_CP_INTC_0_REGS; +CSL_CPINTCRegs* gpCIC1_regs = (CSL_CPINTCRegs*)CSL_CP_INTC_1_REGS; +/*The register pointer for the CIC routing events DSP core. +By default, it is CIC0; but for core 4~7 of C6678, it is CIC1*/ +CSL_CPINTCRegs* gpCIC_regs= (CSL_CPINTCRegs*)CSL_CP_INTC_0_REGS; + +CSL_TpccRegs* gpEDMA_CC0_regs = (CSL_TpccRegs*)CSL_EDMA0CC_REGS; +CSL_TpccRegs* gpEDMA_CC1_regs = (CSL_TpccRegs*)CSL_EDMA1CC_REGS; +CSL_TpccRegs* gpEDMA_CC2_regs = (CSL_TpccRegs*)CSL_EDMA2CC_REGS; +CSL_TpccRegs* gpEDMA_CC_regs[3] = { + (CSL_TpccRegs*)CSL_EDMA0CC_REGS, + (CSL_TpccRegs*)CSL_EDMA1CC_REGS, + (CSL_TpccRegs*)CSL_EDMA2CC_REGS +}; + +CSL_TptcRegs * gpEDMA_TC_0_0_regs=(CSL_TptcRegs *) CSL_EDMA0TC0_REGS; +CSL_TptcRegs * gpEDMA_TC_0_1_regs=(CSL_TptcRegs *) CSL_EDMA0TC1_REGS; +CSL_TptcRegs * gpEDMA_TC_1_0_regs=(CSL_TptcRegs *) CSL_EDMA1TC0_REGS; +CSL_TptcRegs * gpEDMA_TC_1_1_regs=(CSL_TptcRegs *) CSL_EDMA1TC1_REGS; +CSL_TptcRegs * gpEDMA_TC_1_2_regs=(CSL_TptcRegs *) CSL_EDMA1TC2_REGS; +CSL_TptcRegs * gpEDMA_TC_1_3_regs=(CSL_TptcRegs *) CSL_EDMA1TC3_REGS; +CSL_TptcRegs * gpEDMA_TC_2_0_regs=(CSL_TptcRegs *) CSL_EDMA2TC0_REGS; +CSL_TptcRegs * gpEDMA_TC_2_1_regs=(CSL_TptcRegs *) CSL_EDMA2TC1_REGS; +CSL_TptcRegs * gpEDMA_TC_2_2_regs=(CSL_TptcRegs *) CSL_EDMA2TC2_REGS; +CSL_TptcRegs * gpEDMA_TC_2_3_regs=(CSL_TptcRegs *) CSL_EDMA2TC3_REGS; + +CSL_TptcRegs * gpEDMA_TC_regs[10]= { + (CSL_TptcRegs *) CSL_EDMA0TC0_REGS, + (CSL_TptcRegs *) CSL_EDMA0TC1_REGS, + (CSL_TptcRegs *) CSL_EDMA1TC0_REGS, + (CSL_TptcRegs *) CSL_EDMA1TC1_REGS, + (CSL_TptcRegs *) CSL_EDMA1TC2_REGS, + (CSL_TptcRegs *) CSL_EDMA1TC3_REGS, + (CSL_TptcRegs *) CSL_EDMA2TC0_REGS, + (CSL_TptcRegs *) CSL_EDMA2TC1_REGS, + (CSL_TptcRegs *) CSL_EDMA2TC2_REGS, + (CSL_TptcRegs *) CSL_EDMA2TC3_REGS +}; + +CSL_TmrPlusRegs * gpTimer0Regs = (CSL_TmrPlusRegs *)CSL_TIMER_0_REGS; +CSL_TmrPlusRegs * gpTimer1Regs = (CSL_TmrPlusRegs *)CSL_TIMER_1_REGS; +CSL_TmrPlusRegs * gpTimer2Regs = (CSL_TmrPlusRegs *)CSL_TIMER_2_REGS; +CSL_TmrPlusRegs * gpTimer3Regs = (CSL_TmrPlusRegs *)CSL_TIMER_3_REGS; +CSL_TmrPlusRegs * gpTimer4Regs = (CSL_TmrPlusRegs *)CSL_TIMER_4_REGS; +CSL_TmrPlusRegs * gpTimer5Regs = (CSL_TmrPlusRegs *)CSL_TIMER_5_REGS; +CSL_TmrPlusRegs * gpTimer6Regs = (CSL_TmrPlusRegs *)CSL_TIMER_6_REGS; +CSL_TmrPlusRegs * gpTimer7Regs = (CSL_TmrPlusRegs *)CSL_TIMER_7_REGS; +CSL_TmrPlusRegs * gpTimer8Regs = (CSL_TmrPlusRegs *)(CSL_TIMER_7_REGS+(CSL_TIMER_7_REGS-CSL_TIMER_6_REGS)); +CSL_TmrPlusRegs * gpTimerRegs[9] = { + (CSL_TmrPlusRegs *)CSL_TIMER_0_REGS, + (CSL_TmrPlusRegs *)CSL_TIMER_1_REGS, + (CSL_TmrPlusRegs *)CSL_TIMER_2_REGS, + (CSL_TmrPlusRegs *)CSL_TIMER_3_REGS, + (CSL_TmrPlusRegs *)CSL_TIMER_4_REGS, + (CSL_TmrPlusRegs *)CSL_TIMER_5_REGS, + (CSL_TmrPlusRegs *)CSL_TIMER_6_REGS, + (CSL_TmrPlusRegs *)CSL_TIMER_7_REGS, + (CSL_TmrPlusRegs *)(CSL_TIMER_7_REGS+(CSL_TIMER_7_REGS-CSL_TIMER_6_REGS)) +}; + +/*MPU for peripherals registers and data space*/ +CSL_MpuRegs * gpMPU0_regs= (CSL_MpuRegs *)CSL_MPU_0_REGS; +CSL_MpuRegs * gpMPU1_regs= (CSL_MpuRegs *)CSL_MPU_1_REGS; +CSL_MpuRegs * gpMPU2_regs= (CSL_MpuRegs *)CSL_MPU_2_REGS; +CSL_MpuRegs * gpMPU3_regs= (CSL_MpuRegs *)CSL_MPU_3_REGS; + +CSL_Emif4fRegs * gpDDR_regs= (CSL_Emif4fRegs *)CSL_DDR3_EMIF_CONFIG_REGS; +unsigned int gDSP_Core_Speed_Hz= 1000000000; //DSP core clock speed in Hz +TDSP_Board_Type gDSP_board_type= UNKNOWN; + +/*----------------------------------------------* + * module-wide global variables * + *----------------------------------------------*/ + +/*----------------------------------------------* + * constants * + *----------------------------------------------*/ + +/*----------------------------------------------* + * macros * + *----------------------------------------------*/ + +/*----------------------------------------------* + * routines' implementations * + *----------------------------------------------*/ + +/***************************************************************************** + Prototype : KeyStone_main_PLL_init + Description : DSP core PLL configuration + DSP core will be configured to run at ref_clock_MHz*multiplier/divisor + Input : float ref_clock_MHz + unsigned int multiplier: 1~4096 + unsigned int divisor: 1~64 + Output : + Return Value : + + History : + 1.Date : 2010-12-12 + Author : Brighton Feng + Modification : Created function + 2.Date : May 19, 2013 + Author : Brighton Feng + Modification : update parameter check; replace constant with macro + +*****************************************************************************/ +void KeyStone_main_PLL_init (float ref_clock_MHz, + unsigned int multiplier, unsigned int divisor) +{ + unsigned int i; + + if(0==divisor) + { + puts("Error: PLL input divider = 0"); + return; + } + + if(64SECCTL & PLLCTL_BYPASS_MASK) + { + /*a. In MAINPLLCTL1, write ENSAT = 1 (for optimal PLL operation) */ + gpBootCfgRegs->CORE_PLL_CTL1 |= PLLCTL1_ENSAT_MASK; /*Set ENSAT bit = 1*/ + + /*b. In PLLCTL, write PLLEN = 0 (bypass enabled in PLL controller mux) */ + gpPLLC_regs->PLLCTL &= ~CSL_PLLC_PLLCTL_PLLEN_MASK; + + /*c. In PLLCTL, write PLLENSRC = 0 (enable PLLEN to control PLL controller mux */ + gpPLLC_regs->PLLCTL &= ~CSL_PLLC_PLLCTL_PLLENSRC_MASK; + + /*d. Wait 4 cycles of the reference clock CLKIN (to make sure the PLL controller */ + /*mux switches properly to the bypass) */ + for(i=0; i< 4; i++) + asm(" nop 5"); + + /*e. In SECCTL, write BYPASS = 1 (bypass enabled in PLL mux) */ + gpPLLC_regs->SECCTL |= PLLCTL_BYPASS_MASK; + + /*f. In PLLCTL, write PLLPWRDN = 1 (power down the PLL) */ + gpPLLC_regs->PLLCTL |= CSL_PLLC_PLLCTL_PLLPWRDN_MASK; //Power down the PLL + + /*g. Wait for at least 5 ��s based on the reference clock CLKIN (PLL power down */ + /*toggling time) */ + for(i=0; i< 1000; i++) + asm(" nop 5"); + + /*h. In PLLCTL, write PLLPWRDN = 0 (power up the PLL) */ + gpPLLC_regs->PLLCTL &= ~CSL_PLLC_PLLCTL_PLLPWRDN_MASK; // Power up PLL + } + else + { + /*a. In PLLCTL, write PLLEN = 0 (bypass enabled in PLL controller mux) */ + gpPLLC_regs->PLLCTL &= (~CSL_PLLC_PLLCTL_PLLEN_MASK); + + /*b. In PLLCTL, write PLLENSRC = 0 (enable PLLEN to control PLL controller mux */ + gpPLLC_regs->PLLCTL &= (~CSL_PLLC_PLLCTL_PLLENSRC_MASK); + + /*c. Wait 4 cycles of the reference clock CLKIN (to make sure the PLL controller */ + /*mux switches properly to the bypass) */ + for(i=0; i< 4*multiplier/divisor; i++) + asm(" nop 5"); + } + + /*4. PLLM is split in two different registers. Program PLLM[5:0] in PLL multiplier */ + /*control register (PLLM) and PLLM[12:6] in MAINPLLCTL0 register */ + /*5. BWADJ is split in two different registers. Program BWADJ[7:0] in */ + /*MAINPLLCTL0 and BWADJ[11:8] in MAINPLLCTL1 register. BWADJ value */ + /*must be set to ((PLLM + 1) >> 1) - 1) */ + /*6. Program PLLD in MAINPLLCTL0 register */ + gpBootCfgRegs->CORE_PLL_CTL0 = ((multiplier-1)<PLLM= (multiplier*2-1)&0x3F; + gpBootCfgRegs->CORE_PLL_CTL1 &= ~PLLCTL1_BWADJ_MASK; + gpBootCfgRegs->CORE_PLL_CTL1 |= (multiplier-1)>>8; /*BWADJ[11:8]*/ + + /*7. In SECCTL, write OD (Output Divide) = 1 (that is divide-by-2) */ + gpPLLC_regs->SECCTL &= ~PLLCTL_OD_MASK; + gpPLLC_regs->SECCTL |= 1<PLLSTAT) & CSL_PLLC_PLLSTAT_GOSTAT_MASK); + + /* Step 8b: Program the RATIO field in PLLDIVn to the desired new divide-down rate. + If RATIO field is changed, the PLL controller will flag the change in the + corresponding bit of DCHANGE*/ + gpPLLC_regs->PLLDIV1_3[3-1] = (3-1) | CSL_PLLC_PLLDIV1_3_DNEN_MASK; //Set PLLDIV3 + gpPLLC_regs->PLLDIV4_16[4-4] = (5-1) | CSL_PLLC_PLLDIV4_16_DNEN_MASK; //Set PLLDIV4 + gpPLLC_regs->PLLDIV4_16[7-4] = (6-1) | CSL_PLLC_PLLDIV4_16_DNEN_MASK; //Set PLLDIV7 + + /* Step 8c: Set GOSET bit in PLLCMD to initiate the GO operation to change the divide + values and align the SYSCLKs as programmed */ + gpPLLC_regs->PLLCMD |= CSL_PLLC_PLLCMD_GOSET_MASK; + + /*Step 8d/e: Read the GOSTAT bit in PLLSTAT to make sure the bit returns to 0 to + indicate that the GO operation has completed */ + while((gpPLLC_regs->PLLSTAT) & CSL_PLLC_PLLSTAT_GOSTAT_MASK); +#endif + + /*9. In PLLCTL , write PLLRST = 1 (PLL reset is asserted)*/ + gpPLLC_regs->PLLCTL |= CSL_PLLC_PLLCTL_PLLRST_MASK; + + /*10. Wait for at least 7 ��s based on the reference clock CLKIN (PLL reset time) */ + for(i=0; i< 2000; i++) + asm(" nop 5"); + + /*11. In PLLCTL, write PLLRST = 0 (PLL reset is released) */ + gpPLLC_regs->PLLCTL &= ~CSL_PLLC_PLLCTL_PLLRST_MASK; + + /*12. Wait for at least 2000 �� CLKIN cycles �� (PLLD + 1) (PLL lock time) */ + for(i=0; i< 400*multiplier; i++) + asm(" nop 5"); + + /*13. In SECCTL, write BYPASS = 0 (enable PLL mux to switch to PLL mode) */ + gpPLLC_regs->SECCTL &= ~PLLCTL_BYPASS_MASK; + + /*14. Set the PLLEN bit in PLLCTL to 1 to enable PLL mode*/ + gpPLLC_regs->PLLCTL |= CSL_PLLC_PLLCTL_PLLEN_MASK; + +} +/***************************************************************************** + Prototype : KeyStone_PLL_init + Description : Config the PLL of PA and DDR + target clock speed will be ref_clock_MHz/inputDivisor*multiplier/outputDivisor + Input : unsigned int inputDivisor + unsigned int multiplier + unsigned int outputDivisor + Output : None + Return Value : 0 for success, other value for error + + History : + 1.Date : May 18, 2013 + Author : Brighton Feng + Modification : Created function + +*****************************************************************************/ +int KeyStone_PLL_init (PLL_ControlRegs * PLL_Regs, unsigned int inputDivisor, + unsigned int multiplier, unsigned int outputDivisor) +{ + if(0==inputDivisor) + { + puts("Error: PLL input divider = 0"); + return 1; + } + + if(64PLL_CTL1 = PLLCTL1_ENSAT_MASK; + + /*2. In PLLCTL0, write BYPASS = 1 (set the PLL in Bypass)*/ + PLL_Regs->PLL_CTL0 |= PLLCTL_BYPASS_MASK; + + /*3. Program PLLM and PLLD in PLLCTL0 register*/ + /*4. Program BWADJ[7:0] in PLLCTL0 and BWADJ[11:8] in PLLCTL1 register. + BWADJ value must be set to ((PLLM + 1) >> 1) �C 1)*/ + PLL_Regs->PLL_CTL0 = ((multiplier/2-1)<PLL_CTL1 &= ~PLLCTL1_BWADJ_MASK; + PLL_Regs->PLL_CTL1 |= (multiplier/2-1)>>8; /*BWADJ[11:8]*/ + + /*5. In PLLCTL1, write PLLRST = 1 (PLL is reset)*/ + PLL_Regs->PLL_CTL1 |= PLLCTL1_PLLRESET_MASK; //Set RESET bit = 1 + + /*6. Wait for at least 7 us based on the reference clock (PLL reset time)*/ + TSC_delay_us(7); + + /*For PASS, In PASSPLLCTL1, write PLLSELECT = 1 + (for selecting the output of PA PLL as the input to PASS)*/ + if(PLL_Regs==(PLL_ControlRegs *)gpBootCfgRegs->PA_PLL_CTL0) + PLL_Regs->PLL_CTL1 |= PLLCTL1_PAPLL_MASK; + + /*7. In PLLCTL1, write PLLRST = 0 (PLL reset is released)*/ + PLL_Regs->PLL_CTL1 &= ~PLLCTL1_PLLRESET_MASK; //Clear RESET bit + + /*8. Wait for at least 500 * REFCLK cycles * (PLLD + 1) (PLL lock time)*/ + TSC_delay_us(500); + + /*9. In PLLCTL0, write BYPASS = 0 (switch to PLL mode)*/ + PLL_Regs->PLL_CTL0 &= ~PLLCTL_BYPASS_MASK ; + + return 0; +} +/***************************************************************************** + Prototype : KeyStone_PASS_PLL_init + Description : Config the PASS PLL + target clock speed will be ref_clock_MHz/divisor*multiplier + Input : float ref_clock_MHz + unsigned int multiplier: 1~4096 + unsigned int divisor: 1~64 + Output : None + Return Value : + + History : + 1.Date : 2013-2-14 + Author : Brighton Feng + Modification : Created function + +*****************************************************************************/ +void KeyStone_PASS_PLL_init (float ref_clock_MHz, + unsigned int multiplier, unsigned int divisor) +{ + //output divisor for PASS PLL should be 2 + if(0==KeyStone_PLL_init((PLL_ControlRegs *)&gpBootCfgRegs->PA_PLL_CTL0, + divisor, multiplier*2, 2)) + { + printf("Initialize PASS PLL clock = %.2fMHz/%dx%d = %.3fMHz\n", + ref_clock_MHz, divisor, multiplier, + ref_clock_MHz*multiplier/divisor); + } +} + +/***************************************************************************** + Prototype : KeyStone_DDR_PLL_init + Description : Config the DDR PLL + target clock speed will be ref_clock_MHz/divisor*multiplier + Input : float ref_clock_MHz + unsigned int multiplier: 1~4096 + unsigned int divisor: 1~64 + Output : None + Return Value : + + History : + 1.Date : 2013-8-18 + Author : Brighton Feng + Modification : Created function + +*****************************************************************************/ +void KeyStone_DDR_PLL_init (float ref_clock_MHz, + unsigned int multiplier, unsigned int divisor) +{ + //output divisor for DDR PLL should be 2 + if(0==KeyStone_PLL_init((PLL_ControlRegs *)&gpBootCfgRegs->DDR3_PLL_CTL0, + divisor, multiplier, 2)) + { + printf("Initialize DDR speed = %.2fMHzx/%dx%d = %.3fMTS\n", + ref_clock_MHz, divisor, multiplier, + ref_clock_MHz*multiplier/divisor); + } +} + +/*===============================TSC===================================*/ +unsigned int cycle_measure_overhead=50; +/***************************************************************************** + Prototype : calc_cycle_measure_overhead + Description : calclucate the cycles measurement overhead + Input : None + Output : None + Return Value : + + History : + 1.Date : 2010/12/12 + Author : Brighton Feng + Modification : Created function + +*****************************************************************************/ +void calc_cycle_measure_overhead() +{ + unsigned int cycle_cold, cycle_warm; + cycle_cold= TSCL; + cycle_cold = TSC_getDelay(cycle_cold); + cycle_warm= TSCL; + cycle_warm = TSC_getDelay(cycle_warm); + cycle_measure_overhead = (cycle_cold + cycle_warm)/2; +} + +/***************************************************************************** + Prototype : TSC_init + Description : Initialize Time stamp counter to measure cycles + Input : None + Output : None + Return Value : + + History : + 1.Date : 2010/12/12 + Author : Brighton Feng + Modification : Created function + +*****************************************************************************/ +void TSC_init() +{ + TSCL = 0; /* Enable the TSC */ + calc_cycle_measure_overhead(); +} + +/***************************************************************************** + Prototype : TSC_delay_ms + Description : Implement the delay function in millisecond + Input : Uint32 ms + Output : None + Return Value : + + History : + 1.Date : 2010/12/12 + Author : Brighton Feng + Modification : Created function + +*****************************************************************************/ +void TSC_delay_ms(Uint32 ms) +{ + volatile unsigned long long startTSC, currentTSC; + unsigned long long delay_cycles; + Uint32 tscl, tsch; + + tscl= TSCL; + tsch= TSCH; + startTSC= _itoll(tsch,tscl); + + delay_cycles= ((unsigned long long)ms*gDSP_Core_Speed_Hz/1000); + + do + { + tscl= TSCL; + tsch= TSCH; + currentTSC= _itoll(tsch,tscl); + } + while((currentTSC-startTSC)TGCR) + { + gpTimerRegs[timer_num]->TGCR= 0; + gpTimerRegs[timer_num]->TCR= 0; + } +} + + /***************************************************************************** + Prototype : Timer64_Init + Description : Initialize a 64-bit timer + Input : Timer64_Config * tmrCfg + Output : None + Return Value : + + History : + 1.Date : 2010/12/12 + Author : Brighton Feng + Modification : Created function + +*****************************************************************************/ +void Timer64_Init(Timer64_Config * tmrCfg) +{ + Reset_Timer(tmrCfg->timer_num); + + gpTimerRegs[tmrCfg->timer_num]->CNTLO= 0; + gpTimerRegs[tmrCfg->timer_num]->CNTHI= 0; + + /*please note, in clock mode, two timer periods generate a clock, + one timer period output high voltage level, the other timer period + output low voltage level, so, the timer period should be half to the + desired output clock period*/ + if(TIMER_PERIODIC_CLOCK==tmrCfg->timerMode) + tmrCfg->period= tmrCfg->period/2; + + /*the value written into period register is the expected value minus one*/ + gpTimerRegs[tmrCfg->timer_num]->PRDLO= _loll(tmrCfg->period-1); + gpTimerRegs[tmrCfg->timer_num]->PRDHI= _hill(tmrCfg->period-1); + if(tmrCfg->reload_period>1) + { + gpTimerRegs[tmrCfg->timer_num]->RELLO= _loll(tmrCfg->reload_period-1); + gpTimerRegs[tmrCfg->timer_num]->RELHI= _hill(tmrCfg->reload_period-1); + } + + if(TIMER_WATCH_DOG==tmrCfg->timerMode) + { + gpTimerRegs[tmrCfg->timer_num]->TGCR= + /*Select watch-dog mode*/ + (CSL_TMR_TIMMODE_WDT<timerMode) + { + gpTimerRegs[tmrCfg->timer_num]->TGCR= TMR_TGCR_PLUSEN_MASK + /*for plus featuers, dual 32-bit unchained timer mode should be used*/ + |(CSL_TMR_TIMMODE_DUAL_UNCHAINED<timer_num]->INTCTL_STAT= TMR_INTCTLSTAT_EN_ALL_CLR_ALL; + } + else + { + gpTimerRegs[tmrCfg->timer_num]->TGCR= + /*Select 64-bit general timer mode*/ + (CSL_TMR_TIMMODE_GPT<timer_num]->EMUMGT_CLKSPD = (gpTimerRegs[tmrCfg->timer_num]->EMUMGT_CLKSPD& + ~(CSL_TMR_EMUMGT_CLKSPD_FREE_MASK|CSL_TMR_EMUMGT_CLKSPD_SOFT_MASK)); + + if(TIMER_WATCH_DOG==tmrCfg->timerMode) + { + /*enable watchdog timer*/ + gpTimerRegs[tmrCfg->timer_num]->WDTCR = CSL_TMR_WDTCR_WDEN_MASK + |(CSL_TMR_WDTCR_WDKEY_CMD1<timer_num]->TCR= + (CSL_TMR_CLOCK_INP_NOGATE<pulseWidth<timer_num]->WDTCR = CSL_TMR_WDTCR_WDEN_MASK + |(CSL_TMR_WDTCR_WDKEY_CMD2<timerMode) + { + gpTimerRegs[tmrCfg->timer_num]->TCR= + (CSL_TMR_CLOCK_INP_NOGATE<pulseWidth<timerMode) + { + gpTimerRegs[tmrCfg->timer_num]->TCR= + (CSL_TMR_CLOCK_INP_NOGATE<pulseWidth<timerMode) + { + gpTimerRegs[tmrCfg->timer_num]->TCR= + (CSL_TMR_CLOCK_INP_NOGATE<pulseWidth<timer_num]->TCR= + (CSL_TMR_CLOCK_INP_NOGATE<pulseWidth<WDTCR = + (CSL_TMR_WDTCR_WDKEY_CMD1<WDTCR = + (CSL_TMR_WDTCR_WDKEY_CMD2<0x3FFFFFFF) + { + printf("Enable power domain %d timeout!\n", pwrDmnNum); + return -2; + } + } + } + + /* Enable the clocks too*/ + CSL_PSC_setModuleNextState (moduleNum, PSC_MODSTATE_ENABLE); + + /* Start the state transition */ + CSL_PSC_startStateTransition (pwrDmnNum); + + /* Wait until the state transition process is completed. */ + while (!CSL_PSC_isStateTransitionDone (pwrDmnNum)) + { + if(TSC_count_cycle_from(uiStartTSC)>0x3FFFFFFF) + { + printf("Enable clock domain %d timeout!\n", moduleNum); + return -2; + } + } + + /* Return PSC status */ + if ((CSL_PSC_getPowerDomainState(pwrDmnNum) == PSC_PDSTATE_ON) && + (CSL_PSC_getModuleState (moduleNum) == PSC_MODSTATE_ENABLE)) + { + /*Ready for use */ + return 0; + } + else + { + /*Return error */ + return -1; + } +} +/***************************************************************************** + Prototype : KeyStone_disable_PSC_module + Description : Disable the PSC module in KeyStone device + Input : Uint32 pwrDmnNum + Uint32 moduleNum + Output : None + Return Value : + + History : + 1.Date : 2010/2/12 + Author : Brighton Feng + Modification : Created function + +*****************************************************************************/ +Int32 KeyStone_disable_PSC_module (Uint32 pwrDmnNum, Uint32 moduleNum) +{ + Uint32 uiStartTSC= TSCL; + + /* disable the clocks*/ + CSL_PSC_setModuleNextState (moduleNum, PSC_MODSTATE_SWRSTDISABLE); + + /* Start the state transition */ + CSL_PSC_startStateTransition (pwrDmnNum); + + /* Wait until the state transition process is completed. */ + while (!CSL_PSC_isStateTransitionDone (pwrDmnNum)) + { + if(TSC_count_cycle_from(uiStartTSC)>0x3FFFFFFF) + { + printf("Disable clock domain %d timeout!\n", moduleNum); + return -2; + } + } + + /* Return PSC status */ + if (CSL_PSC_getModuleState (moduleNum) == PSC_MODSTATE_SWRSTDISABLE) + { + /*Ready for use */ + return 0; + } + else + { + /*Return error */ + return -1; + } + +} +/***************************************************************************** + Prototype : KeyStone_disable_PSC_Power_Domain + Description : Disable the PSC power domain + Input : Uint32 pwrDmnNum + Output : None + Return Value : + + History : + 1.Date : 2010/12/12 + Author : Brighton Feng + Modification : Created function + +*****************************************************************************/ +Int32 KeyStone_disable_PSC_Power_Domain (Uint32 pwrDmnNum) +{ + Uint32 uiStartTSC= TSCL; + + /* Set Power domain to OFF */ + CSL_PSC_disablePowerDomain (pwrDmnNum); + + /* Start the state transition */ + CSL_PSC_startStateTransition (pwrDmnNum); + + /* Wait until the state transition process is completed. */ + while (!CSL_PSC_isStateTransitionDone (pwrDmnNum)) + { + if(TSC_count_cycle_from(uiStartTSC)>0x3FFFFFFF) + { + printf("Disable power domain %d timeout!\n", pwrDmnNum); + return -2; + } + } + + /* Return PSC status */ + if (CSL_PSC_getPowerDomainState(pwrDmnNum) == PSC_PDSTATE_OFF) + { + /*Ready for use */ + return 0; + } + else + { + /*Return error */ + return -1; + } + +} + +/*============================EDMA=====================================*/ + /***************************************************************************** + Prototype : EDMA_channel_TC_cfg + Description : Setup uiChannel of an EDMA to use uiTC + Input : Uint32 uiCC + Uint32 uiChannel + Uint32 uiTC + Output : None + Return Value : + + History : + 1.Date : 2010/12/12 + Author : Brighton Feng + Modification : Created function + +*****************************************************************************/ +void EDMA_channel_TC_cfg (Uint32 uiCC, + Uint32 uiChannel, Uint32 uiTC) +{ + gpEDMA_CC_regs[uiCC]->TPCC_DMAQNUM[uiChannel/8] = + (gpEDMA_CC_regs[uiCC]->TPCC_DMAQNUM[uiChannel/8]&(~(0xF<<((uiChannel&7)*4)))) + |(uiTC<<((uiChannel&7)*4)); +} +/***************************************************************************** + Prototype : EDMA_TC_priority_cfg + Description : Setup uiChannel of an EDMA TC priority + Input : Uint32 uiCC + Uint32 uiPri + Uint32 uiTC + Output : None + Return Value : + + History : + 1.Date : 2010/12/12 + Author : Brighton Feng + Modification : Created function + +*****************************************************************************/ +void EDMA_TC_priority_cfg(Uint32 uiCC, + Uint32 uiPri, Uint32 uiTC) +{ + gpEDMA_CC_regs[uiCC]->TPCC_QUEPRI= + (gpEDMA_CC_regs[uiCC]->TPCC_QUEPRI&(~(0xF<<((uiTC&3)*4)))) + |(uiPri<<((uiTC&3)*4)); +} +/***************************************************************************** + Prototype : EDMA_init + Description : Initialize all EDMA registers and clear the event + Input : None + Output : None + Return Value : + + History : + 1.Date : 2010/12/12 + Author : Brighton Feng + Modification : Created function + +*****************************************************************************/ +void EDMA_init () +{ + int i; + unsigned int * uipPaRAM; + + /*clear PaRAM*/ + uipPaRAM= (unsigned int *)&(gpEDMA_CC0_regs->PARAMSET[0]); + for(i=0; i<8*CSL_EDMA3_TPCC0_NUM_PARAMSETS; i++) + *uipPaRAM++=0; + + uipPaRAM= (unsigned int *)&(gpEDMA_CC1_regs->PARAMSET[0]); + for(i=0; i<8*CSL_EDMA3_TPCC1_NUM_PARAMSETS; i++) + *uipPaRAM++=0; + + uipPaRAM= (unsigned int *)&(gpEDMA_CC2_regs->PARAMSET[0]); + for(i=0; i<8*CSL_EDMA3_TPCC2_NUM_PARAMSETS; i++) + *uipPaRAM++=0; + + /*Assign PaRAM for different channels*/ + for(i=0; iTPCC_DCHMAP[i] = i<< CSL_TPCC_TPCC_DCHMAP0_PAENTRY_SHIFT; + + for(i=0; iTPCC_DCHMAP[i] = i<< CSL_TPCC_TPCC_DCHMAP0_PAENTRY_SHIFT; + + for(i=0; iTPCC_DCHMAP[i] = i<< CSL_TPCC_TPCC_DCHMAP0_PAENTRY_SHIFT; + + /*Assign TC/Queue for different channels*/ + gpEDMA_CC0_regs->TPCC_DMAQNUM[0]= 0x10101010; + gpEDMA_CC0_regs->TPCC_DMAQNUM[1]= 0x10101010; + + gpEDMA_CC1_regs->TPCC_DMAQNUM[0]= 0x32103210; + gpEDMA_CC1_regs->TPCC_DMAQNUM[1]= 0x32103210; + gpEDMA_CC1_regs->TPCC_DMAQNUM[2]= 0x32103210; + gpEDMA_CC1_regs->TPCC_DMAQNUM[3]= 0x32103210; + gpEDMA_CC1_regs->TPCC_DMAQNUM[4]= 0x32103210; + gpEDMA_CC1_regs->TPCC_DMAQNUM[5]= 0x32103210; + gpEDMA_CC1_regs->TPCC_DMAQNUM[6]= 0x32103210; + gpEDMA_CC1_regs->TPCC_DMAQNUM[7]= 0x32103210; + + gpEDMA_CC2_regs->TPCC_DMAQNUM[0]= 0x32103210; + gpEDMA_CC2_regs->TPCC_DMAQNUM[1]= 0x32103210; + gpEDMA_CC2_regs->TPCC_DMAQNUM[2]= 0x32103210; + gpEDMA_CC2_regs->TPCC_DMAQNUM[3]= 0x32103210; + gpEDMA_CC2_regs->TPCC_DMAQNUM[4]= 0x32103210; + gpEDMA_CC2_regs->TPCC_DMAQNUM[5]= 0x32103210; + gpEDMA_CC2_regs->TPCC_DMAQNUM[6]= 0x32103210; + gpEDMA_CC2_regs->TPCC_DMAQNUM[7]= 0x32103210; + + /*clear any events and status*/ + gpEDMA_CC0_regs->TPCC_ECR= 0xFFFF; + gpEDMA_CC0_regs->TPCC_EECR= 0xFFFF; + gpEDMA_CC0_regs->TPCC_ICR= 0xFFFF; + gpEDMA_CC0_regs->TPCC_IECR= 0xFFFF; + gpEDMA_CC0_regs->TPCC_EMCR= 0xFFFF; + gpEDMA_CC0_regs->TPCC_QEMCR= 0xFFFF; + gpEDMA_CC0_regs->TPCC_CCERRCLR= 0xFFFF; + gpEDMA_CC0_regs->TPCC_SECR= 0xFFFF; + + gpEDMA_CC1_regs->TPCC_ECR= 0xFFFFFFFF; + gpEDMA_CC1_regs->TPCC_ECRH= 0xFFFFFFFF; + gpEDMA_CC1_regs->TPCC_EECR= 0xFFFFFFFF; + gpEDMA_CC1_regs->TPCC_EECRH= 0xFFFFFFFF; + gpEDMA_CC1_regs->TPCC_ICR= 0xFFFFFFFF; + gpEDMA_CC1_regs->TPCC_ICRH= 0xFFFFFFFF; + gpEDMA_CC1_regs->TPCC_IECR= 0xFFFFFFFF; + gpEDMA_CC1_regs->TPCC_IECRH= 0xFFFFFFFF; + gpEDMA_CC1_regs->TPCC_EMCR= 0xFFFFFFFF; + gpEDMA_CC1_regs->TPCC_EMCRH= 0xFFFFFFFF; + gpEDMA_CC1_regs->TPCC_QEMCR= 0xFFFFFFFF; + gpEDMA_CC1_regs->TPCC_CCERRCLR= 0xFFFF; + gpEDMA_CC1_regs->TPCC_SECR= 0xFFFFFFFF; + gpEDMA_CC1_regs->TPCC_SECRH= 0xFFFFFFFF; + + gpEDMA_CC2_regs->TPCC_ECR= 0xFFFFFFFF; + gpEDMA_CC2_regs->TPCC_ECRH= 0xFFFFFFFF; + gpEDMA_CC2_regs->TPCC_EECR= 0xFFFFFFFF; + gpEDMA_CC2_regs->TPCC_EECRH= 0xFFFFFFFF; + gpEDMA_CC2_regs->TPCC_ICR= 0xFFFFFFFF; + gpEDMA_CC2_regs->TPCC_ICRH= 0xFFFFFFFF; + gpEDMA_CC2_regs->TPCC_IECR= 0xFFFFFFFF; + gpEDMA_CC2_regs->TPCC_IECRH= 0xFFFFFFFF; + gpEDMA_CC2_regs->TPCC_EMCR= 0xFFFFFFFF; + gpEDMA_CC2_regs->TPCC_EMCRH= 0xFFFFFFFF; + gpEDMA_CC2_regs->TPCC_QEMCR= 0xFFFFFFFF; + gpEDMA_CC2_regs->TPCC_CCERRCLR= 0xFFFF; + gpEDMA_CC2_regs->TPCC_SECR= 0xFFFFFFFF; + gpEDMA_CC2_regs->TPCC_SECRH= 0xFFFFFFFF; + + for(i=0; iTPTC_ERRCLR= 0xF; + + //enable error interrupt + gpEDMA_TC_regs[i]->TPTC_ERREN= + (1<TPCC_EESR= 1<<(uiChannel); + } + else + { + //enable the EDMA channel + gpEDMA_CC_regs[uiCC]->TPCC_EESRH= 1<<(uiChannel-32); + } +} + +void EDMA_event_disable(Uint32 uiCC, Uint32 uiChannel) +{ + if(uiChannel<32) + { + //disable the EDMA channel + gpEDMA_CC_regs[uiCC]->TPCC_EECR= 1<<(uiChannel); + } + else + { + //disable the EDMA channel + gpEDMA_CC_regs[uiCC]->TPCC_EECRH= 1<<(uiChannel-32); + } +} + +void EDMA_interrupt_enable(Uint32 uiCC, Uint32 uiIntNum) +{ + if(uiIntNum<32) + { + //enable the EDMA channel interrupt + gpEDMA_CC_regs[uiCC]->TPCC_IESR= 1<<(uiIntNum); + } + else + { + //enable the EDMA channel interrupt + gpEDMA_CC_regs[uiCC]->TPCC_IESRH= 1<<(uiIntNum-32); + } +} + +void EDMA_interrupt_disable(Uint32 uiCC, Uint32 uiIntNum) +{ + if(uiIntNum<32) + { + //disable the EDMA channel interrupt + gpEDMA_CC_regs[uiCC]->TPCC_IECR= 1<<(uiIntNum); + } + else + { + //disable the EDMA channel interrupt + gpEDMA_CC_regs[uiCC]->TPCC_IECRH= 1<<(uiIntNum-32); + } +} + +/***************************************************************************** + Prototype : EDMA_wait + Description : wait the pending EDMA complete + Input : EDMA_CC_Channel_Num CC_channel + Output : None + Return Value : + + History : + 1.Date : 2012/10/30 + Author : Brighton Feng + Modification : Created function + +*****************************************************************************/ +void EDMA_wait(EDMA_CC_Channel_Num CC_channel) +{ + CSL_TpccRegs* EDMACCRegs; + unsigned int uiChannel; + volatile Uint32 * TPCC_IPR; + volatile Uint32 * TPCC_ICR; + + EDMACCRegs= gpEDMA_CC_regs[CC_channel>>16]; + uiChannel = CC_channel&0xFF; + + if(uiChannel<32) + { + TPCC_IPR= &EDMACCRegs->TPCC_IPR; + TPCC_ICR= &EDMACCRegs->TPCC_ICR; + } + else + { + TPCC_IPR= &EDMACCRegs->TPCC_IPRH; + TPCC_ICR= &EDMACCRegs->TPCC_ICRH; + uiChannel -= 32; + } + + /*wait for completion*/ + while(0==((*TPCC_IPR)&(1<<(uiChannel)))); + + /*clear completion flag*/ + (*TPCC_ICR)= 1<<(uiChannel); +} + +/***************************************************************************** + Prototype : EDMA_Copy + Description : EDMA copy function with manual trigger + Input : unsigned int srcAddr + unsigned int dstAddr + unsigned int byteCount, <64KB + EDMA_CC_Channel_Num CC_channel + DMA_Wait wait + Output : None + Return Value : + + History : + 1.Date : 2012/10/30 + Author : Brighton Feng + Modification : Created function + +*****************************************************************************/ +void EDMA_copy(unsigned int srcAddr, unsigned int dstAddr, + unsigned int byteCount, EDMA_CC_Channel_Num CC_channel, DMA_Wait wait) +{ + CSL_TpccRegs* EDMACCRegs; + unsigned int uiChannel; + volatile Uint32 * TPCC_ESR; + volatile Uint32 * TPCC_IPR; + volatile Uint32 * TPCC_ICR; + + EDMACCRegs= gpEDMA_CC_regs[CC_channel>>16]; + uiChannel = CC_channel&0xFF; + + EDMACCRegs->PARAMSET[uiChannel].OPT= + CSL_EDMA3_OPT_MAKE(CSL_EDMA3_ITCCH_DIS, + CSL_EDMA3_TCCH_DIS, + CSL_EDMA3_ITCINT_DIS, + CSL_EDMA3_TCINT_EN, + uiChannel, + CSL_EDMA3_TCC_NORMAL, + CSL_EDMA3_FIFOWIDTH_NONE, + CSL_EDMA3_STATIC_DIS, + CSL_EDMA3_SYNC_A, + CSL_EDMA3_ADDRMODE_INCR, + CSL_EDMA3_ADDRMODE_INCR); + EDMACCRegs->PARAMSET[uiChannel].SRC= GLOBAL_ADDR(srcAddr); + EDMACCRegs->PARAMSET[uiChannel].A_B_CNT=CSL_EDMA3_CNT_MAKE(byteCount&0xFFFF, 1); + EDMACCRegs->PARAMSET[uiChannel].DST= GLOBAL_ADDR(dstAddr); + EDMACCRegs->PARAMSET[uiChannel].SRC_DST_BIDX= 0; + EDMACCRegs->PARAMSET[uiChannel].LINK_BCNTRLD= CSL_EDMA3_LINKBCNTRLD_MAKE(0xFFFF, 1); + EDMACCRegs->PARAMSET[uiChannel].SRC_DST_CIDX= 0; + EDMACCRegs->PARAMSET[uiChannel].CCNT= 1; + + if(uiChannel<32) + { + TPCC_ESR= &EDMACCRegs->TPCC_ESR; + TPCC_IPR= &EDMACCRegs->TPCC_IPR; + TPCC_ICR= &EDMACCRegs->TPCC_ICR; + } + else + { + TPCC_ESR= &EDMACCRegs->TPCC_ESRH; + TPCC_IPR= &EDMACCRegs->TPCC_IPRH; + TPCC_ICR= &EDMACCRegs->TPCC_ICRH; + uiChannel -= 32; + } + + /*Manually trigger the EDMA*/ + (*TPCC_ESR)= 1<<(uiChannel); + + if(wait) + { + /*wait for completion*/ + while(0==((*TPCC_IPR)&(1<<(uiChannel)))); + + /*clear completion flag*/ + (*TPCC_ICR)= 1<<(uiChannel); + } +} + +/***************************************************************************** + Prototype : EDMA_fill + Description : EDMA fill function with manual trigger + Input : unsigned int address, must align to 8 bytes boundary + unsigned long long data + unsigned int byteCount, must be multiple of 8 + EDMA_CC_Channel_Num CC_channel + Output : None + Return Value : + + History : + 1.Date : 2013/8/11 + Author : Brighton Feng + Modification : Created function + +*****************************************************************************/ +void EDMA_fill(unsigned int address, unsigned long long data, + unsigned int byteCount, EDMA_CC_Channel_Num CC_channel) +{ + int i; + CSL_TpccRegs* EDMACCRegs; + unsigned int uiChannel, uiChannelShift, uiBCNT; + volatile Uint32 * TPCC_ESR; + volatile Uint32 * TPCC_IPR; + volatile Uint32 * TPCC_ICR; + unsigned long long tempBuf[128/8]; + Uint32 tempBufSize=128, headerSize, tailSize; + + if(tempBufSize>byteCount) + tempBufSize=byteCount; + + for(i=0; i< tempBufSize/8; i++) + tempBuf[i]= data; + + /*split the transfer into 3 sections at 128 byte boundary*/ + if(address&127) //header address not start on 128 byte boundary + { + headerSize= 128- (address&127); + if(headerSize>byteCount) + headerSize=byteCount; + EDMA_copy((Uint32)tempBuf, address, headerSize, CC_channel, DMA_WAIT); + address+= headerSize; + byteCount-= headerSize; + } + + if(byteCount&&((address+byteCount)&127))//tail address not start on 128 byte boundary + { + tailSize= (address+byteCount)&127; + EDMA_copy((Uint32)tempBuf, address+byteCount-tailSize, tailSize, CC_channel, DMA_WAIT); + byteCount-= tailSize; + } + + EDMACCRegs= gpEDMA_CC_regs[CC_channel>>16]; + uiChannel = CC_channel&0xFF; + if(uiChannel<32) + { + TPCC_ESR= &EDMACCRegs->TPCC_ESR; + TPCC_IPR= &EDMACCRegs->TPCC_IPR; + TPCC_ICR= &EDMACCRegs->TPCC_ICR; + uiChannelShift= uiChannel; + } + else + { + TPCC_ESR= &EDMACCRegs->TPCC_ESRH; + TPCC_IPR= &EDMACCRegs->TPCC_IPRH; + TPCC_ICR= &EDMACCRegs->TPCC_ICRH; + uiChannelShift= uiChannel - 32; + } + + EDMACCRegs->PARAMSET[uiChannel].OPT= + CSL_EDMA3_OPT_MAKE(CSL_EDMA3_ITCCH_DIS, + CSL_EDMA3_TCCH_DIS, + CSL_EDMA3_ITCINT_DIS, + CSL_EDMA3_TCINT_EN, + uiChannel, + CSL_EDMA3_TCC_NORMAL, + CSL_EDMA3_FIFOWIDTH_NONE, + CSL_EDMA3_STATIC_EN, //keep PARAM unchanged + CSL_EDMA3_SYNC_AB, + CSL_EDMA3_ADDRMODE_INCR, + CSL_EDMA3_ADDRMODE_INCR); + EDMACCRegs->PARAMSET[uiChannel].SRC= GLOBAL_ADDR(tempBuf); + EDMACCRegs->PARAMSET[uiChannel].SRC_DST_BIDX= CSL_EDMA3_BIDX_MAKE(0, 128); + EDMACCRegs->PARAMSET[uiChannel].LINK_BCNTRLD= CSL_EDMA3_LINKBCNTRLD_MAKE(0xFFFF, 0); + EDMACCRegs->PARAMSET[uiChannel].SRC_DST_CIDX= 0; + EDMACCRegs->PARAMSET[uiChannel].CCNT= 1; + + while(byteCount) //the reminding must be multiple of 128 bytes + { + uiBCNT= byteCount/128; + if(uiBCNT>65535) + uiBCNT= 65535; + + EDMACCRegs->PARAMSET[uiChannel].A_B_CNT= CSL_EDMA3_CNT_MAKE(128, uiBCNT); + EDMACCRegs->PARAMSET[uiChannel].DST= GLOBAL_ADDR(address); + + /*Manually trigger the EDMA*/ + (*TPCC_ESR)= 1<<(uiChannelShift); + + /*wait for completion*/ + while(0==((*TPCC_IPR)&(1<<(uiChannelShift)))); + + /*clear completion flag*/ + (*TPCC_ICR)= 1<<(uiChannelShift); + + byteCount -= uiBCNT*128; + address += uiBCNT*128; + } +} + +/***************************************************************************** + Prototype : IDMA_wait + Description : wait the pending IDMA complete + Input : None + Output : None + Return Value : + + History : + 1.Date : 2012/10/28 + Author : Brighton Feng + Modification : Created function + +*****************************************************************************/ +void IDMA_wait() +{ + /* Wait until copying is completed */ + while (gpCGEM_regs->IDMA1_STAT); +} +/***************************************************************************** + Prototype : IDMA_copy + Description : implement the data copy via IDMA + Input : unsigned int srcAddr + unsigned int dstAddr + unsigned int byteCount, <64KB + IDMA_Wait wait + Output : None + Return Value : + + History : + 1.Date : 2012/10/28 + Author : Brigthon + Modification : Created function + +*****************************************************************************/ +void IDMA_copy(unsigned int srcAddr, unsigned int dstAddr, + unsigned int byteCount, DMA_Wait wait) +{ + gpCGEM_regs->IDMA1_SOURCE= srcAddr; + gpCGEM_regs->IDMA1_DEST= dstAddr; + gpCGEM_regs->IDMA1_COUNT= byteCount&0xFFFC; + + if(wait) + { + /* Wait until copying is completed */ + while (gpCGEM_regs->IDMA1_STAT); + } +} +/***************************************************************************** + Prototype : EDMA_CC_error_handler + Description : Edma channel controller error processing + Input : Uint32 edmaNum, EDMA module number (0~2) + Output : None + Return Value : + + History : + 1.Date : 2012/11/7 + Author : Brighton Feng + Modification : Created function + +*****************************************************************************/ +void EDMA_CC_error_handler(Uint32 edmaNum) +{ + int i; + CSL_TpccRegs* EDMACCRegs= gpEDMA_CC_regs[edmaNum]; + Uint32 EMR, EMRH= 0, QEMR, CCERR; + + //read error status + EMR= EDMACCRegs->TPCC_EMR; + QEMR= EDMACCRegs->TPCC_QEMR; + CCERR= EDMACCRegs->TPCC_CCERR; + exception_record.status.ext_sts.info.edma.CC_info.EMR= EMR; + exception_record.status.ext_sts.info.edma.CC_info.QEMR= QEMR; + exception_record.status.ext_sts.info.edma.CC_info.CCERR= CCERR; + + //clear error status + EDMACCRegs->TPCC_EMCR= EMR; + EDMACCRegs->TPCC_QEMCR= QEMR; + EDMACCRegs->TPCC_CCERRCLR= CCERR; + + //channel 32~63 for EDMA CC1 and CC2 + if(0TPCC_EMRH; + exception_record.status.ext_sts.info.edma.CC_info.EMRH= EMRH; + + //clear error status + EDMACCRegs->TPCC_EMCRH= EMRH; + } + + for(i=0; i<32; i++) + { + if((EMR>>i)&1) + printf(" EDMA Channel %d event missed.\n", i); + if((EMRH>>i)&1) + printf(" EDMA Channel %d event missed.\n", i+32); + } + + for(i=0; i<8; i++) + { + if((QEMR>>i)&1) + printf(" QDMA Channel %d event missed.\n", i); + } + + for(i=0; i<4; i++) + { + if((CCERR>>i)&1) + printf(" Queue %d Watermark/threshold has been exceeded.\n", i); + } + + if(CCERR&CSL_TPCC_TPCC_CCERR_TCCERR_MASK) + puts(" Total number of allowed TCCs has been reached."); + +} +/***************************************************************************** + Prototype : EDMA_TC_error_handler + Description : Edma transfer controller error processing + Input : CSL_TptcRegs * edmaTCRegs + Output : None + Return Value : + + History : + 1.Date : 2012/11/7 + Author : Brighton Feng + Modification : Created function + +*****************************************************************************/ +void EDMA_TC_error_handler(CSL_TptcRegs * edmaTCRegs) +{ + Uint32 ERRSTAT, ERRDET, STAT; + + //read error status + ERRSTAT= edmaTCRegs->TPTC_ERRSTAT; + ERRDET= edmaTCRegs->TPTC_ERRDET; + exception_record.status.ext_sts.info.edma.TC_info.ERRSTAT=ERRSTAT ; + exception_record.status.ext_sts.info.edma.TC_info.ERRDET= ERRDET; + + //clear error + edmaTCRegs->TPTC_ERRCLR= ERRSTAT; + + if(ERRSTAT&CSL_TPTC_TPTC_ERRSTAT_MMRAERR_MASK) + puts(" User attempted to read or write to an invalid address in configuration memory map."); + if(ERRSTAT&CSL_TPTC_TPTC_ERRSTAT_TRERR_MASK) + puts(" TR detected that violates constant addressing mode transfer (SAM or DAM is set) alignment rules or has ACNT or BCNT== 0."); + if(ERRSTAT&CSL_TPTC_TPTC_ERRSTAT_BUSERR_MASK) + { + puts(" EDMA3TC has detected an error at source or destination address."); + + STAT= ERRDET&CSL_TPTC_TPTC_ERRDET_STAT_MASK; + + if(STAT>=8) + printf(" write error (%d). ",STAT); + else if(STAT>=1) + printf(" read error (%d). ",STAT); + else + printf(" no error!?"); + + printf("TCC= %d. TCINTEN= %d. TCCHEN= %d\n", + (ERRDET&CSL_TPTC_TPTC_ERRDET_TCC_MASK)>>CSL_TPTC_TPTC_ERRDET_TCC_SHIFT, + (ERRDET&CSL_TPTC_TPTC_ERRDET_TCINTEN_MASK)>>CSL_TPTC_TPTC_ERRDET_TCINTEN_SHIFT, + (ERRDET&CSL_TPTC_TPTC_ERRDET_TCCHEN_MASK)>>CSL_TPTC_TPTC_ERRDET_TCCHEN_SHIFT); + } + +} +/***************************************************************************** + Prototype : EDMA_error_handler + Description : EDMA error processing function + Input : Uint32 edmaNum + Uint32 errorFlag + error flag bit fields are defined as below + (follow the sequence in CIC) + 0 EDMACC_ERRINT EDMA3CC error interrupt + 2 EDMATC_ERRINT0 EDMA3TC0 error interrupt + 3 EDMATC_ERRINT1 EDMA3TC1 error interrupt + 4 EDMATC_ERRINT2 EDMA3TC2 error interrupt + 5 EDMATC_ERRINT3 EDMA3TC3 error interrupt + Output : None + Return Value : + + History : + 1.Date : 2012/10/28 + Author : Brighton Feng + Modification : Created function + +*****************************************************************************/ +void EDMA_error_handler(Uint32 edmaNum, Uint32 errorFlag) +{ + int i; + + printf(" EDMA module %d error\n", edmaNum); + if(errorFlag&1) + EDMA_CC_error_handler(edmaNum); + + errorFlag >>= 2; + + for(i=0; i<4; i++) + { + if(errorFlag&(1<MPLKCMD = (1<MPLK[i] = mem_prot_key[i]; + } + + /*3. Write a 1 to the LOCK field of the MPLKCMD register. This engages the lock.*/ + gpCGEM_regs->MPLKCMD = (1<MPLKSTAT&CSL_CGEM_MPLKSTAT_LK_MASK)); +} + +/***************************************************************************** + Prototype : unlock_mem_prot_regs + Description : unlock memory protection registers + Input : None + Output : None + Return Value : + + History : + 1.Date : 2010/12/12 + Author : Brighton Feng + Modification : Created function + +*****************************************************************************/ +#pragma CODE_SECTION (unlock_mem_prot_regs, ".text:Core_MPAX") +void unlock_mem_prot_regs() +{ + int i; + + /*1. Write a 1 to the KEYR field in the MPLKCMD register. This resets some internal + status for the MPLK0 through the MPLK3 registers.*/ + gpCGEM_regs->MPLKCMD = (1<MPLK[i] = mem_prot_key[i]; + } + + /*3. Write a 1 to the UNLOCK field in the MPLKCMD register. If the key written in + step 2 matches the stored key, the hardware disengages the lock. If the key written + in step 2 does not match, the hardware signals an exception. The hardware + reports the fault address as the address of the MPLKCMD register.*/ + gpCGEM_regs->MPLKCMD = (1<MPLKSTAT&CSL_CGEM_MPLKSTAT_LK_MASK)); +} + +/***************************************************************************** + Prototype : L1_MPPA_setup + Description : setup the memory protection for local L1 memory + Input : volatile Uint32 MPPA_regs[], Uint32 MPPA[] + Output : None + Return Value : + +usage example: + Uint32 MPPA[16]= + { + MP_LOCAL|MP_SR|MP_UR, //page 0 for read only + MP_LOCAL|MP_SR|MP_SW|MP_UR|MP_UW, //page 1 for read/write + ...... + } + ...... + L1_MPPA_setup(gpCGEM_regs->L1PMPPA, MPPA); + + History : + 1.Date : 2012/12/6 + Author : Brighton Feng + Modification : Created function + +*****************************************************************************/ +void L1_MPPA_setup(volatile Uint32 MPPA_regs[], Uint32 MPPA[]) +{ + int i; + + if(gpCGEM_regs->MPLKSTAT&CSL_CGEM_MPLKSTAT_LK_MASK) + unlock_mem_prot_regs(); + + /*clear any memory protection fault*/ + gpCGEM_regs->L1PMPFCR = 1; + gpCGEM_regs->L1DMPFCR = 1; + + /*setup the memory protection attributes for 32 pages*/ + for(i=0; i<16; i++) + { + MPPA_regs[i] = MPPA[i]; + } + + lock_mem_prot_regs(); +} + +/***************************************************************************** + Prototype : L1P_memory_protection_cfg + Description : config "AccessPermisionMask" for L1P + Input : Uint32 AccessPermisionMask + Output : None + Return Value : +*****************************************************************************/ +void L1P_memory_protection_cfg(Uint32 AccessPermisionMask) +{ + int i; + + if(gpCGEM_regs->MPLKSTAT&CSL_CGEM_MPLKSTAT_LK_MASK) + unlock_mem_prot_regs(); + + /*clear any memory protection fault*/ + gpCGEM_regs->L1PMPFCR = 1; + + /*set L1P only for cacheable local execution, disable all external access*/ + for(i=0; i<16; i++) + { + gpCGEM_regs->L1PMPPA[i] = AccessPermisionMask; + } + + lock_mem_prot_regs(); +} + +/***************************************************************************** + Prototype : L1D_memory_protection_cfg + Description : config "AccessPermisionMask" for L1P + Input : Uint32 AccessPermisionMask + Output : None + Return Value : +*****************************************************************************/ +void L1D_memory_protection_cfg(Uint32 AccessPermisionMask) +{ + int i; + + if(gpCGEM_regs->MPLKSTAT&CSL_CGEM_MPLKSTAT_LK_MASK) + unlock_mem_prot_regs(); + + /*clear any memory protection fault*/ + gpCGEM_regs->L1DMPFCR = 1; + + /*set L1P only for cacheable local execution, disable all external access*/ + for(i=0; i<16; i++) + { + gpCGEM_regs->L1DMPPA[i] = AccessPermisionMask; + } + + lock_mem_prot_regs(); +} + +/***************************************************************************** + Prototype : L1_cache_protection + Description : protect L1 as cache + Input : None + Output : None + Return Value : + + History : + 1.Date : 2012/10/28 + Author : Brighton Feng + Modification : Created function + +*****************************************************************************/ +void L1_cache_protection() +{ + /*set L1P only for cacheable local execution, disable all external access*/ + L1P_memory_protection_cfg(0); + + /*set L1D only for cacheable local read/write, disable all external access*/ + L1D_memory_protection_cfg(0); +} + + +/***************************************************************************** + Prototype : LL2_MPPA_setup + Description : setup the memory protection for local L2 memory + Input : Uint32 MPPA[] + Output : None + Return Value : +usage example: + Uint32 MPPA[32]= + { + MP_LOCAL|MP_SX|MP_UX, //page 0 for local code only + MP_LOCAL|MP_SR|MP_SW|MP_UR|MP_UW, //page 1 for local data only + ...... + } + ...... + LL2_MPPA_setup(MPPA); + + History : + 1.Date : 2012/10/5 + Author : Brighton Feng + Modification : Created function + +*****************************************************************************/ +void LL2_MPPA_setup(Uint32 MPPA[]) +{ + int i; + + if(gpCGEM_regs->MPLKSTAT&CSL_CGEM_MPLKSTAT_LK_MASK) + unlock_mem_prot_regs(); + + /*clear any memory protection fault*/ + gpCGEM_regs->L2MPFCR = 1; + + /*setup the memory protection attributes for 32 pages*/ + for(i=0; i<32; i++) + { + gpCGEM_regs->L2MPPA[i] = MPPA[i]; + } + + lock_mem_prot_regs(); +} + +/***************************************************************************** + Prototype : LL2_Memory_Protection_cfg + Description : config "AccessPermisionMask" for local L2 memory section from + "startAddress" with "byteCount" size + Input : Uint32 startAddress + Uint32 byteCount + Uint32 AccessPermisionMask + Output : None + Return Value : + + History : + 1.Date : 2012/10/5 + Author : Brighton Feng + Modification : Created function + +*****************************************************************************/ +void LL2_Memory_Protection_cfg(Uint32 startAddress, + Uint32 byteCount, Uint32 AccessPermisionMask) +{ + int i; + Uint32 uiEndAddress; + Uint32 uiPageIndex, uiNumPages, uiPageSize, uiPageAddressMask, uiPageShift; + TDSP_Board_Type DSP_Board_Type; + + if(gpCGEM_regs->MPLKSTAT&CSL_CGEM_MPLKSTAT_LK_MASK) + unlock_mem_prot_regs(); + + DSP_Board_Type = KeyStone_Get_dsp_board_type(); + + /*L2 memory protection size is 32KB for TCI6614, C6670, + it is 16KB for C6678*/ + uiPageSize= 32*1024; + uiPageAddressMask= 32*1024-1; + uiPageShift= 15; + if(C6678_EVM == DSP_Board_Type) + { + uiPageSize= 16*1024; + uiPageAddressMask= 16*1024-1; + uiPageShift= 14; + } + + if(startAddress>=0x10800000) + { + printf("LL2 memory protection start Address 0x%x is not a local address\n", + startAddress); + startAddress &= 0xFFFFFF; /*convert to local address*/ + } + uiEndAddress= startAddress+ byteCount; + + if(startAddress&uiPageAddressMask) + { + printf("LL2 memory protection start Address 0x%x does not align to page boundary\n", + startAddress); + startAddress &= (~uiPageAddressMask); + } + uiPageIndex= (startAddress-0x800000)>>uiPageShift; + + byteCount= uiEndAddress- startAddress; + if(byteCount&uiPageAddressMask) + { + printf("LL2 memory protection section size 0x%x is not multiple of page size\n", + byteCount); + byteCount = (byteCount+uiPageSize)&(~uiPageAddressMask); + } + uiNumPages= byteCount>>uiPageShift; + + for(i= 0; iL2MPPA[uiPageIndex+i] = AccessPermisionMask; + + lock_mem_prot_regs(); +} + +/***************************************************************************** + Prototype : KeyStone_CorePac_AID_map + Description : map CorePac AID to PrivID: + map_table[0] assign the PrivID for AID0, + map_table[1] assign the PrivID for AID1 + ...... + map_table[5] assign the PrivID for AID5 + Input : Uint8 map_table[] + Output : None + Return Value : + + History : + 1.Date : 2012/10/5 + Author : Zhan + Modification : Created function + +*****************************************************************************/ +void KeyStone_CorePac_AID_map(Uint8 map_table[]) +{ + int i; + Uint32 *PAMAP= (Uint32 *)&(gpCGEM_regs->PAMAP0); + + /*map all PrivID to AIDx by default*/ + for(i=0; i<16; i++) + PAMAP[i]= CSL_CGEM_PAMAP0_AID_MASK; + + /*map AID0~AID5*/ + for(i=0; i<6; i++) + { + if(map_table[i]<16) /*PrivID must be less than 16*/ + PAMAP[map_table[i]]= i; + } +} + +/***************************************************************************** + Prototype : KeyStone_PrivID_Remap + Description : privilege ID remap to AID + Input : int privID + int AID + Output : None + Return Value : + + History : + 1.Date : 2012/10/5 + Author : Zhan + Modification : Created function + +*****************************************************************************/ +void KeyStone_PrivID_Remap(int privID, int AID) +{ + volatile unsigned int * pamapReg = NULL; + unsigned int val = 0; + + pamapReg = (volatile unsigned int *)(&gpCGEM_regs->PAMAP0 + privID); + + if(AID >= MAX_AID_NUM) + AID = 0; + val = *pamapReg; + + val &= (~CSL_CGEM_PAMAP0_AID_MASK); + + val |= ((AID<>4)) + { + printf("Segment replacement address 0x%x does not start from power-of-2 boundary corresponds to segment size 0x%x.\n", + RADDR, SegementSize); + RADDR &= (~(SegSizeMask>>4)); + printf("Extended replacement address to 0x%x.\n", RADDR); + } + + MPAX_regs->MPAXH= BADDR|(SegSizeBits-1); + MPAX_regs->MPAXL= RADDR|AccessPermisionMask; + +} + +/***************************************************************************** + Prototype : KeyStone_XMC_MPAX_setup + Description : configure multiple MPAX segments in XMC with a configuration + table. + Please note, the code of this function or the data used by this function + (stack, parameters...) can not be put in the segment that will be modified + by this function. Normally, to put this function and its related data in + LL2 is a good idea. + Input : MPAX_Config MPAX_cfg[] + Uint32 firstSeg + Uint32 numSegs + Output : None + Return Value : + + History : + 1.Date : 2012/10/15 + Author : Brighton Feng + Modification : Created function + +*****************************************************************************/ +#pragma CODE_SECTION (KeyStone_XMC_MPAX_setup, ".text:Core_MPAX") +void KeyStone_XMC_MPAX_setup(MPAX_Config MPAX_cfg[], + Uint32 firstSeg, Uint32 numSegs) +{ + int i; + + if(firstSeg >= 16) + { + printf("The XMC MPAX segment number %d >= 16, not supported.\n ", firstSeg); + return; + } + + if(gpCGEM_regs->MPLKSTAT&CSL_CGEM_MPLKSTAT_LK_MASK) + unlock_mem_prot_regs(); + + /*CAUTION: + A MPAX segment can only be modified when there is no access to the space + of this segment. Any data in cache or prefetch buffer from the space of this + segment must be writeback and invalidated before the segment modification. + It is recommended to configure the MPAX at the very beginning of application + software before any shared memory is used. Code and data for CorePac MPAX + configuration should be allocated in LL2. + If a MPAX segment must be modified on-the-fly, the safer way is, to write + the new configuration to a unused higher segment, and then clear the old + segment. This is based on the fact that higher numbered segments take + precedence over lower numbered segments. */ + CACHE_wbInvAllL2(CACHE_WAIT); + CSL_XMC_invalidatePrefetchBuffer(); + _mfence(); + _mfence(); //ensure all writeback invalidate have completed. + + for(i=numSegs-1; i>=0 ; i--) + { + KeyStone_MPAX_seg_setup((MPAX_Regs *)&gpXMC_regs->XMPAX[firstSeg+i], + MPAX_cfg[i].BADDR, MPAX_cfg[i].RADDR, + MPAX_cfg[i].SegementSize, MPAX_cfg[i].AccessPermisionMask); + } + + lock_mem_prot_regs(); +} + +/***************************************************************************** + Prototype : KeyStone_SMS_MPAX_setup + Description : configure multiple MPAX segments in SMS of MSMC with a conf- + iguration table + Input : MPAX_Config MPAX_cfg[] + Uint32 firstSeg + Uint32 numSegs + Uint32 PrivID + Output : None + Return Value : + + History : + 1.Date : 2012/10/15 + Author : Brighton Feng + Modification : Created function + +*****************************************************************************/ +void KeyStone_SMS_MPAX_setup(MPAX_Config MPAX_cfg[], + Uint32 firstSeg, Uint32 numSegs, Uint32 PrivID) +{ + int i; + + if( gpMSMC_regs->SMS_MPAX_LCKSTAT&(1<=0 ; i--) + KeyStone_MPAX_seg_setup( + (MPAX_Regs *)&gpMSMC_regs->SMS_MPAX_PER_PRIVID[PrivID].SMS[firstSeg+i], + MPAX_cfg[i].BADDR, MPAX_cfg[i].RADDR, + MPAX_cfg[i].SegementSize, MPAX_cfg[i].AccessPermisionMask); + + CSL_MSMC_lockSMS(PrivID); +} + +/***************************************************************************** + Prototype : KeyStone_SES_MPAX_setup + Description : configure multiple MPAX segments in SES of MSMC with a conf- + iguration table + Input : MPAX_Config MPAX_cfg[] + Uint32 firstSeg + Uint32 numSegs + Uint32 PrivID + Output : None + Return Value : + + History : + 1.Date : 2012/10/15 + Author : Brighton Feng + Modification : Created function + +*****************************************************************************/ +void KeyStone_SES_MPAX_setup(MPAX_Config MPAX_cfg[], + Uint32 firstSeg, Uint32 numSegs, Uint32 PrivID) +{ + int i; + + if( gpMSMC_regs->SES_MPAX_LCKSTAT&(1<=0 ; i--) + KeyStone_MPAX_seg_setup( + (MPAX_Regs *)&gpMSMC_regs->SES_MPAX_PER_PRIVID[PrivID].SES[firstSeg+i], + MPAX_cfg[i].BADDR, MPAX_cfg[i].RADDR, + MPAX_cfg[i].SegementSize, MPAX_cfg[i].AccessPermisionMask); + + CSL_MSMC_lockSES(PrivID); +} + +/***************************************************************************** + Prototype : KeyStone_MSMC_MP_interrupt_en + Description : Enable MSMC Memory protection error interrupt for PrivIDs + indicated by "PRIVID_MASK" + Input : Uint32 PRIVID_MASK + Output : None + Return Value : + + History : + 1.Date : 2012/10/15 + Author : Zhan + Modification : Created function + +*****************************************************************************/ +void KeyStone_MSMC_MP_interrupt_en(Uint32 PRIVID_MASK) +{ + if(gpMSMC_regs->CFGLCKSTAT&CSL_MSMC_CFGLCKSTAT_WSTAT_MASK) + CSL_MSMC_unlockNonMPAX(); + + /*clear MP fault record*/ + gpMSMC_regs->SMPFCR = 1; + + /*clear interrupt error status flag*/ + gpMSMC_regs->SMIRC = (PRIVID_MASK)<SMIESTAT |= (PRIVID_MASK<> + CSL_CGEM_L2MPFSR_FID_SHIFT; + + printf(" memory protection exception caused by master with ID %d at 0x%x\n", + master_id, MPFAR); + } + + if (MPFSR & CSL_CGEM_L2MPFSR_UX_MASK) { + puts(" User Execute violation"); + } + if (MPFSR & CSL_CGEM_L2MPFSR_UW_MASK) { + puts(" User Write violation"); + } + if (MPFSR & CSL_CGEM_L2MPFSR_UR_MASK) { + puts(" User Read violation"); + } + if (MPFSR & CSL_CGEM_L2MPFSR_SX_MASK) { + puts(" Supervisor Execute violation"); + } + if (MPFSR & CSL_CGEM_L2MPFSR_SW_MASK) { + puts(" Supervisor Write violation"); + } + if (MPFSR & CSL_CGEM_L2MPFSR_SR_MASK) { + puts(" Supervisor Read violation"); + } + +} + +/***************************************************************************** + Prototype : KeyStone_MSMC_protection_exception_handler + Description : MSMC memory protection processing + Input : None + Output : None + Return Value : +*****************************************************************************/ +void KeyStone_MSMC_protection_exception_handler() +{ + unsigned int master_id; + unsigned int priv_id; + unsigned int address; + unsigned int NM; + + address = gpMSMC_regs->SMPFAR; + + master_id = (gpMSMC_regs->SMPFR&CSL_MSMC_SMPFR_FMSTID_MASK)>> + CSL_MSMC_SMPFR_FMSTID_SHIFT; + priv_id = (gpMSMC_regs->SMPFR&CSL_MSMC_SMPFR_FPID_MASK)>> + CSL_MSMC_SMPFR_FPID_SHIFT; + + exception_record.status.ext_sts.info.memory.fault_address= address; + exception_record.status.ext_sts.info.memory.fault_status.SMPFR= gpMSMC_regs->SMPFR; + + NM = (gpMSMC_regs->SMPFXR & CSL_MSMC_SMPFXR_NM_MASK) >> CSL_MSMC_SMPFXR_NM_SHIFT; + + printf(" memory protection exception caused by master %d (PrivID= %d) at address 0x%x\n", + master_id, priv_id, address); + + if(1 == NM) + { + printf(" Fault is caused by the address not matching any of the segment BADDR\n"); + } + + if(gpMSMC_regs->CFGLCKSTAT&CSL_MSMC_CFGLCKSTAT_WSTAT_MASK) + CSL_MSMC_unlockNonMPAX(); + /*clear fault record*/ + gpMSMC_regs->SMPFCR = 1; + /*clear interrupt error status flag*/ + gpMSMC_regs->SMIRC = (1<PROG_START_ADDRESS = uiStartAddress; + MPPA_regs->PROG_END_ADDRESS = uiEndAddress; + MPPA_regs->PROG_MPPA = AccessPermisionMask; +} + +/***************************************************************************** + Prototype : KeyStone_MPU_setup + Description : peripherals MPU ranges configuration + Input : Uint32 uiMPU_num: number of the MPU to be setup + MPU_Range_Config MPU_cfg[]: MPU ranges configuration table + Uint32 numRangeCfg: number of ranges to be configured + Output : None + Return Value : + + History : + 1.Date : 2012/12/15 + Author : Brighton Feng + Modification : Created function +*****************************************************************************/ +void KeyStone_MPU_setup(Uint32 uiMPU_num, + MPU_Range_Config MPU_cfg[], Uint32 numRangeCfg) +{ + int i; + unsigned int mpuNumProgmableRange; + CSL_MpuRegs * mpuRegs; + + /*For Turbo Nyquist, add following code to modify initial value, + Or user can modify the initail values directly*/ + if(5==uiMPU_num) + TN_MPU5_constant(); + + mpuRegs= gpMPU_regs[uiMPU_num]; + + mpuNumProgmableRange = (mpuRegs->CONFIG & CSL_MPU_CONFIG_NUM_PROG_MASK)>>CSL_MPU_CONFIG_NUM_PROG_SHIFT; + if(mpuNumProgmableRange == 0) + { + mpuNumProgmableRange = 16; + } + + if(numRangeCfg>mpuNumProgmableRange) + { + printf("MPU %d programmable ranges %d < %d.\n", + uiMPU_num, mpuNumProgmableRange, numRangeCfg); + numRangeCfg=mpuNumProgmableRange; + } + else if(numRangeCfg gstruMpuAddrRange[uiMPU_num].EndAddr) ) + { + printf("The configuration address is out of MPU %d protection range\n", + uiMPU_num); + continue; + } + + KeyStone_MPU_range_setup(&mpuRegs->PROG_REGION[i], + MPU_cfg[i].StartAddr, MPU_cfg[i].EndAddr, + MPU_cfg[i].AccessPermisionMask); + + } + + //clear unused ranges + for( ;iPROG_REGION[i].PROG_MPPA = 0; + } + + //clear status + mpuRegs->FAULT_CLEAR = 1; + mpuRegs->INT_ENABLED_STATUS_CLEAR = + CSL_MPU_INT_ENABLED_STATUS_CLEAR_ENABLED_ADDR_ERR_MASK + |CSL_MPU_INT_ENABLED_STATUS_CLEAR_ENABLED_PROT_ERR_MASK; + + /* enable the interrupt */ + mpuRegs->INT_ENABLE = CSL_MPU_INT_ENABLE_ADDR_ERR_EN_MASK + | CSL_MPU_INT_ENABLE_PROT_ERR_EN_MASK; + + return; +} + +/***************************************************************************** + Prototype : KeyStone_MPU_MPPA_modify + Description : search the range which match a address and then modify + the access permission of that range. + Input : Uint32 uiMPU_num: number of the MPU to be modifed + Uint32 uiAddress: address which need modify permision + Uint32 AccessPermisionMask: permission mask for that range + Output : None + Return Value : + + History : + 1.Date : 2012/12/13 + Author : Brighton Feng + Modification : Created function +*****************************************************************************/ +void KeyStone_MPU_MPPA_modify(Uint32 uiMPU_num, + Uint32 uiAddress, Uint32 AccessPermisionMask) +{ + int i; + unsigned int mpuNumProgmableRange; + CSL_MpuRegs * mpuRegs; + + /*For Turbo Nyquist, add following code to modify initial value, + Or user can modify the initail values directly*/ + if(5==uiMPU_num) + TN_MPU5_constant(); + + mpuRegs= gpMPU_regs[uiMPU_num]; + + mpuNumProgmableRange = (mpuRegs->CONFIG & CSL_MPU_CONFIG_NUM_PROG_MASK)>>CSL_MPU_CONFIG_NUM_PROG_SHIFT; + if(mpuNumProgmableRange == 0) + { + mpuNumProgmableRange = 16; + } + + /*search through all ranges*/ + for(i=0; i< mpuNumProgmableRange; i++) + { + /*match with one range*/ + if((uiAddress >= mpuRegs->PROG_REGION[i].PROG_START_ADDRESS) + &&(uiAddress <= mpuRegs->PROG_REGION[i].PROG_END_ADDRESS)) + { + mpuRegs->PROG_REGION[i].PROG_MPPA = AccessPermisionMask; + return; + } + } + + printf("address 0x%08x does not match any range in MPU %d\n", + uiAddress, uiMPU_num); + + return; +} + +/***************************************************************************** + Prototype : KeyStone_MPU_interrupts_enable + Description : enable the all MPU interrupts + Input : None + Output : None + Return Value : + + History : + 1.Date : 2012/10/28 + Author : Brighton Feng + Modification : Created function + +*****************************************************************************/ +void KeyStone_MPU_interrupt_enable(Uint32 uiMPU_num) +{ + if((gpMPU_regs[uiMPU_num]->REVISION&0xFFFF0000)!= + (CSL_MPU_REVISION_RESETVAL&0xFFFF0000)) + { + printf("Can't read MPU%d ID register, make sure corresponding power domain is enabled.", uiMPU_num); + return; + } + + gpMPU_regs[uiMPU_num]->FAULT_CLEAR = 1; + gpMPU_regs[uiMPU_num]->INT_ENABLED_STATUS_CLEAR = + CSL_MPU_INT_ENABLED_STATUS_CLEAR_ENABLED_ADDR_ERR_MASK + |CSL_MPU_INT_ENABLED_STATUS_CLEAR_ENABLED_PROT_ERR_MASK; + gpMPU_regs[uiMPU_num]->INT_ENABLE = CSL_MPU_INT_ENABLE_ADDR_ERR_EN_MASK + |CSL_MPU_INT_ENABLE_PROT_ERR_EN_MASK; + +} +void KeyStone_MPU_interrupts_enable() +{ + int i; + TDSP_Board_Type DSP_Board_Type = KeyStone_Get_dsp_board_type(); + + TN_MPU5_constant(); + + for(i=0; i<4; i++) + { + KeyStone_MPU_interrupt_enable(i); + } + + if((C6670_EVM== DSP_Board_Type) + ||(TCI6614_EVM== DSP_Board_Type)) + { + for(i=4; i<6; i++) + { + /*MPU5 (for BCP) of TCI6614 is only accessible + when BCP is enabled through PSC*/ + if((5==i)&&(TCI6614_EVM== DSP_Board_Type)&& + ((CSL_PSC_getPowerDomainState(5) != PSC_PDSTATE_ON) || + (CSL_PSC_getModuleState (12) != PSC_MODSTATE_ENABLE))) + { + puts("Enable power domain for MPU5 before configure it."); + continue; + } + + KeyStone_MPU_interrupt_enable(i); + } + } + + if(TCI6614_EVM== DSP_Board_Type) + { + for(i=6; i<8; i++) + { + KeyStone_MPU_interrupt_enable(i); + } + } + + return; +} + +char * Peri_MPU_err_type_str[]= +{ + "User execution fault!", + "User write fault!", + "User read fault!", + "Supervisor execution fault!", + "Supervisor write fault!", + "Supervisor read fault!" +}; + +char * Ns_str[]= +{ + "secure", + "non-secure" +}; +/***************************************************************************** + Prototype : KeyStone_peripherals_MPU_fault_status + Description : Print the MPU error information + Input : unsigned int uwFltStatus + unsigned int uwFltAddr + Output : None + Return Value : +*****************************************************************************/ +void KeyStone_peripherals_MPU_fault_status(unsigned int uwFltStatus, + unsigned int uwFltAddr) +{ + unsigned int MSTID; + unsigned int PRIVID; + unsigned int NS; + unsigned int FaultType; + unsigned int BitsCnt; + + MSTID = (uwFltStatus & CSL_MPU_FAULT_STATUS_MSTID_MASK)>>CSL_MPU_FAULT_STATUS_MSTID_SHIFT; + PRIVID = (uwFltStatus & CSL_MPU_FAULT_STATUS_PRIVID_MASK)>>CSL_MPU_FAULT_STATUS_PRIVID_SHIFT; + NS = (uwFltStatus & CSL_MPU_FAULT_STATUS_NS_MASK)>>CSL_MPU_FAULT_STATUS_NS_SHIFT; + printf(" The MSTID %d (PRIVID %d) triggered MPU error at 0x%x with %s access\n", + MSTID, PRIVID, uwFltAddr, Ns_str[NS]); + + FaultType = (uwFltStatus & CSL_MPU_FAULT_STATUS_FAULT_TYPE_MASK) >> CSL_MPU_FAULT_STATUS_FAULT_TYPE_SHIFT; + if(1==(_dotpu4(_bitc4(FaultType), 0x01010101))) + { + BitsCnt= 31 - _lmbd(1, FaultType); + printf(" %s\n",Peri_MPU_err_type_str[BitsCnt]); + } + else if(0x3F == FaultType) + { + puts(" Relaxed cache line fill fault!"); + } + else if(0x12 == FaultType) + { + puts(" Relaxed cache write back fault!"); + } +} +/***************************************************************************** + Prototype : KeyStone_peripherals_MPU_excepiton_handler + Description : peripheral MPU processing + Input : Uint32 uwMpuNum + Output : None + Return Value : +*****************************************************************************/ +void KeyStone_peripherals_MPU_excepiton_handler(Uint32 uwMpuNum) +{ + Uint32 uwStatus; + Uint32 uwFltAddr; + Uint32 uwFltStatus; + CSL_MpuRegs *pstruMpuRegs= gpMPU_regs[uwMpuNum]; + + uwStatus = pstruMpuRegs->INT_ENABLED_STATUS_CLEAR; + if(uwStatus & 0x2) + { + printf(" MPU %d address violation error\n", uwMpuNum); + pstruMpuRegs->INT_ENABLED_STATUS_CLEAR = 2; + } + + if(uwStatus & 0x1) + { + printf(" MPU %d protection violation error\n", uwMpuNum); + pstruMpuRegs->INT_ENABLED_STATUS_CLEAR = 1; + } + + uwFltAddr = pstruMpuRegs->FAULT_ADDRESS; + uwFltStatus = pstruMpuRegs->FAULT_STATUS; + exception_record.status.ext_sts.info.memory.fault_address= uwFltAddr; + exception_record.status.ext_sts.info.memory.fault_status.MPU_FAULT_STATUS= uwFltStatus; + + KeyStone_peripherals_MPU_fault_status(uwFltStatus,uwFltAddr); + pstruMpuRegs->FAULT_CLEAR = 1; + + pstruMpuRegs->EOI = 0; +} + + +/*======================memory EDC=====================================*/ +/***************************************************************************** + Prototype : KeyStone_SL2_EDC_enable + Description : Enable MSMC EDC + Input : scrubCnt, number of MSMC clock cycles between scrubbing + Output : None + Return Value : + + History : + 1.Date : 2012/10/15 + Author : Brighton Feng + Modification : Created function + +*****************************************************************************/ +void KeyStone_SL2_EDC_enable(Uint32 scrubCnt) +{ + if(gpMSMC_regs->CFGLCKSTAT&CSL_MSMC_CFGLCKSTAT_WSTAT_MASK) + CSL_MSMC_unlockNonMPAX(); + + /*Software must wait for the PRR (Parity RAM Ready) bit before making + the first read access to MSMC RAM after reset.*/ + while(0==(gpMSMC_regs->SMEDCC&CSL_MSMC_SMEDCC_PRR_MASK)); + + /* set scrubbing period value */ + if(scrubCnt>255) + scrubCnt= 255; + CSL_MSMC_setCounterBankRefreshRead(scrubCnt); //the scrubbing engine works every scrubCnt*1024 cycle*/ + + /* clear EDC errors and enable EDC event*/ + gpMSMC_regs->SMIRC = 0xf; + gpMSMC_regs->SMIESTAT |= (CSL_MSMC_SMIESTAT_NCSIE_MASK + | CSL_MSMC_SMIESTAT_CSIE_MASK + | CSL_MSMC_SMIESTAT_NCEIE_MASK + | CSL_MSMC_SMIESTAT_CEIE_MASK); + + //enable SL2 EDC + CSL_MSMC_setECM(1); + + CSL_MSMC_lockNonMPAX(); +} + +/***************************************************************************** + Prototype : KeyStone_SL2_EDC_interrupt_en + Description : Enable MSMC EDC error interrupt + Input : None + Output : None + Return Value : + + History : + 1.Date : 2012/10/15 + Author : Brighton Feng + Modification : Created function + +*****************************************************************************/ +void KeyStone_SL2_EDC_interrupt_en() +{ + if(gpMSMC_regs->CFGLCKSTAT&CSL_MSMC_CFGLCKSTAT_WSTAT_MASK) + CSL_MSMC_unlockNonMPAX(); + + /* clear EDC errors*/ + gpMSMC_regs->SMIRC = 0xf; + + /* Enable EDC error interrupt */ + gpMSMC_regs->SMIESTAT |= (CSL_MSMC_SMIESTAT_NCSIE_MASK + | CSL_MSMC_SMIESTAT_CSIE_MASK + | CSL_MSMC_SMIESTAT_NCEIE_MASK + | CSL_MSMC_SMIESTAT_CEIE_MASK); + + CSL_MSMC_lockNonMPAX(); +} + +/***************************************************************************** + Prototype : LL2_EDC_setup + Description : Eenable LL2 EDC and scrub whole LL2 + Input : None + Output : None + Return Value : + + History : + 1.Date : 2012/10/10 + Author : Jane + Modification : Created function + + 2.Date : 2012/10/20 + Author : Brighton Feng + +*****************************************************************************/ +void LL2_EDC_setup() +{ + int i; + unsigned int uiByteCnt= 512*1024; + TDSP_Board_Type DSP_Board_Type; + + /* 1. Disable the EDC */ + CSL_CGEM_disableL2EDC(); + + /* 2. Clear any EDC errors */ + CSL_CGEM_clearL2EDCErrorStatus(1, 1, 1, 1); + + /* 3. Memory Scrubbing with IDMA, generate the parity bits*/ + DSP_Board_Type = KeyStone_Get_dsp_board_type(); + if((DUAL_NYQUIST_EVM == DSP_Board_Type) + ||(C6670_EVM == DSP_Board_Type) + ||(TCI6614_EVM == DSP_Board_Type)) + { + uiByteCnt= 1024*1024; + } + + /*Each IDMA can transfer up to 65532 bytes, + here we transfer 32KB each time*/ + for(i=0; i< (uiByteCnt>>15); i++) + { + IDMA_copy((0x00800000 + i*(1<<15)), (0x00800000 + i*(1<<15)), + (1<<15), DMA_WAIT); + } + + /* 4. Enable the EDC*/ + CSL_CGEM_enableL2EDC(); + gpCGEM_regs->L2EDCEN= (1<= uiLL2EndAddress) + uiLL2_scrub_addr=0x800000; + +} + +/***************************************************************************** + Prototype : L1P_EDC_setup + Description : enable L1P ED and scrub whole L1P + Input : None + Output : None + Return Value : + + History : + 1.Date : 2012/10/10 + Author : Jane + Modification : Created function + + 2.Date : 2012/10/30 + Author : Brighton Feng +*****************************************************************************/ +void L1P_EDC_setup() +{ + Uint32 preL1PMPPA[16]; + + /* 1. Disable the EDC */ + CSL_CGEM_disablePMCErrorDetection(); + + /* 2. Clear any EDC errors */ + CSL_CGEM_clearPMCErrorDetectionStatus(1, 1); + + /* 3. Memory Scrubbing with IDMA, generate the parity bits*/ + memcpy(preL1PMPPA, (void *)gpCGEM_regs->L1PMPPA, 64);//save protection attributes + L1P_memory_protection_cfg(0xFFFF); //enable IDMA access to L1P + IDMA_copy(0x00E00000, 0x00E00000, 32*1024, DMA_WAIT); + L1_MPPA_setup(gpCGEM_regs->L1PMPPA, preL1PMPPA);//restore protection for L1 + + /* 4. Enable the EDC*/ + CSL_CGEM_enablePMCErrorDetection(); +} + +char * LL2_EDC_victim_err_str="LL2 victims"; +char * LL2_EDC_DMA_err_str= "DMA access"; +char * LL2_EDC_L1D_err_str= "L1D access"; +char * LL2_EDC_L1P_err_str= "L1P access"; + +/***************************************************************************** + Prototype : LL2_EDC_handler + Description : LL2 EDC exception/interrupt handler + Input : None + Output : None + Return Value : + + History : + 1.Date : 2012/10/28 + Author : Brighton Feng + Modification : Created function + +*****************************************************************************/ +void LL2_EDC_handler(Bool bCorrected) +{ + /* EDC error during the L1D access */ + Uint8 derr; + /* EDC error during the L1P access */ + Uint8 perr; + /* EDC error during the DMA access*/ + Uint8 dmaerr; + /* EDC error during the L2 victim occurred */ + Uint8 verr; + /* single bit or dual bit EDC error */ + Uint8 nerr; + + char *errStr; + Uint32 errAddr; + + /* Get the all LL2 error status */ + CSL_CGEM_getL2EDCErrorStatus(&derr, &perr, &dmaerr, &verr, &nerr); + + if(derr|perr|dmaerr|verr) + { + errAddr= gpCGEM_regs->L2EDADDR&CSL_CGEM_L2EDADDR_ADDR_MASK; + + exception_record.status.ext_sts.info.memory.fault_address= errAddr; + exception_record.status.ext_sts.info.memory.fault_status.L2EDSTAT= + gpCGEM_regs->L2EDSTAT; + + if(bCorrected) + { + printf(" LL2 EDC (correctable) at bit %d of ",(gpCGEM_regs->L2EDSTAT& + CSL_CGEM_L2EDSTAT_BITPOS_MASK)>>CSL_CGEM_L2EDSTAT_BITPOS_SHIFT); + + //scrub 64 bytes including the error address to correct the error + if(perr) //by L1P access + IDMA_copy(errAddr&0xFFFFFFC0, errAddr&0xFFFFFFC0, 64, DMA_WAIT); + else + { + volatile Uint32 * uipAddress= (volatile Uint32 *)(errAddr&0xFFFFFFC0); + /*read one word into a cache line, and write to make it dirty, + which will be automatically written back sooner or later*/ + *uipAddress= *uipAddress; + } + } + else + { + printf(" LL2 EDC error (non-correctable) at "); + } + errStr = (char *)(perr * (Uint32)LL2_EDC_L1P_err_str + + derr * (Uint32)LL2_EDC_L1D_err_str + + verr * (Uint32)LL2_EDC_victim_err_str + + dmaerr * (Uint32)LL2_EDC_DMA_err_str); + + printf("address 0x%x caused by %s.\n", + errAddr, + errStr); + + if(0==(gpCGEM_regs->L2EDADDR&CSL_CGEM_L2EDADDR_RAM_MASK)) + { + printf(" Error detected in Way %d of L2 cache\n", + (gpCGEM_regs->L2EDADDR&CSL_CGEM_L2EDADDR_WAY_MASK)>>CSL_CGEM_L2EDADDR_WAY_SHIFT); + } + + printf(" total non-correctable error number= %d, total correctable error number= %d.\n", + gpCGEM_regs->L2EDCNEC, gpCGEM_regs->L2EDCPEC); + + CSL_CGEM_clearL2EDCErrorStatus(derr, perr, dmaerr, verr); + } + else + { + puts(" Enter LL2 EDC handler, but no error flag is set!"); + } +} +/***************************************************************************** + Prototype : L1P_ED_handler + Description : L1P EDC processing + Input : None + Output : None + Return Value : + + History : + 1.Date : 2012/10/28 + Author : Brighton Feng + Modification : Created function + +*****************************************************************************/ +void L1P_ED_handler() +{ + Uint32 errAddr; + Uint8 errRAM; + + /* EDC error during DMA access */ + Uint8 dmaerr; + /* EDC error during program fetch access */ + Uint8 perr; + + /* Read PMC EDC status*/ + CSL_CGEM_getPMCErrorDetectionStatus(&dmaerr, &perr); + + if(perr|dmaerr) + { + CSL_CGEM_getPMCErrorInfo(&errAddr, &errRAM); + + exception_record.status.ext_sts.info.memory.fault_address= errAddr*32; + exception_record.status.ext_sts.info.memory.fault_status.L1PEDSTAT= + gpCGEM_regs->L1PEDSTAT; + + if(errRAM) + printf(" L1P RAM "); + else + printf(" L1P Cache "); + + printf("parity check error caused by "); + + if(perr == 1) + { + printf("program fetch "); + + /*flush wrong code in L1P. Code will be refetched from L2*/ + CACHE_invL1p((void *)NRP, 64, CACHE_WAIT); + } + else if(dmaerr == 1) + { + printf("DMA "); + } + printf("at address 0x%x\n", errAddr*32); + + CSL_CGEM_clearPMCErrorDetectionStatus(dmaerr,perr); + } +} + + +/***************************************************************************** + Prototype : KeyStone_SL2_EDC_handler + Description : SL2 EDC Processing + Input : None + Output : None + Return Value : + + History : + 1.Date : 2012/10/28 + Author : Brighton Feng + Modification : Created function + +*****************************************************************************/ +void KeyStone_SL2_EDC_handler() +{ + /* EDC correctable error during scrubbing cycle */ + Uint8 cses; + /* EDC non-correctable error during scrubbing cycle */ + Uint8 ncses; + /* EDC correctable error during SRAM access*/ + Uint8 cees; + /* EDC non-correctable error during SRAM access*/ + Uint8 ncees; + /* protection fault status*/ + Uint16 pfeStat; + + /* error address */ + Uint32 errAddr, bitPos, PrivID; + + if(gpMSMC_regs->CFGLCKSTAT&CSL_MSMC_CFGLCKSTAT_WSTAT_MASK) + CSL_MSMC_unlockNonMPAX(); + + CSL_MSMC_getPendingInterrupts(&pfeStat, &cees, &ncees, &cses, &ncses); + + exception_record.status.ext_sts.info.memory.fault_status.SMESTAT= + gpMSMC_regs->SMESTAT; + + if((cses == 1)||(ncses == 1)) + { + if(cses == 1) + { + /*scrubbing engine report address offset from 0*/ + errAddr = (gpMSMC_regs->SMCEA&0xFFFFFF)+0xc000000; + exception_record.status.ext_sts.info.memory.fault_address= errAddr; + + bitPos = (gpMSMC_regs->SMCEA&CSL_MSMC_SMCEA_ESYN_MASK) + >>CSL_MSMC_SMCEA_ESYN_SHIFT; + printf("SL2 Correctable error occurred at bit %d of address 0x%x by scrubbing\n", + bitPos, errAddr); + } + if(ncses == 1) + { + /*scrubbing engine report address offset from 0*/ + errAddr = gpMSMC_regs->SMNCEA+0xc000000; + exception_record.status.ext_sts.info.memory.fault_address= errAddr; + + printf("SL2 Non-correctable error occurred at address 0x%x by scrubbing\n", errAddr); + } + printf("%d correctable errors, %d non-correctable errors occurred during scrubbing.\n", + (gpMSMC_regs->SMSECC&CSL_MSMC_SMSECC_SCEC_MASK) + >>CSL_MSMC_SMSECC_SCEC_SHIFT, + (gpMSMC_regs->SMSECC&CSL_MSMC_SMSECC_SNCEC_MASK) + >>CSL_MSMC_SMSECC_SNCEC_SHIFT); + } + if(cees == 1) + { + volatile Uint32 scrubValue; + + errAddr = gpMSMC_regs->SMCERRAR; + exception_record.status.ext_sts.info.memory.fault_address= errAddr; + + //scrub the address to correct the error + scrubValue= *(volatile Uint32 *)errAddr; //touch to cach + *(volatile Uint32 *)errAddr= scrubValue; //make cache dirty + CACHE_wbInvL2((void *)errAddr, 32, CACHE_WAIT); + + bitPos = (gpMSMC_regs->SMCERRXR&CSL_MSMC_SMCERRXR_ESYN_MASK) + >>CSL_MSMC_SMCERRXR_ESYN_SHIFT; + PrivID = (gpMSMC_regs->SMCERRXR&CSL_MSMC_SMCERRXR_SEPID_MASK) + >>CSL_MSMC_SMCERRXR_SEPID_SHIFT; + printf("SL2 Correctable error occurred at bit %d of address 0x%x by PrivID %d ", + bitPos, errAddr, PrivID); + if(gpMSMC_regs->SMCERRXR&CSL_MSMC_SMCERRXR_SER_MASK) + printf("(not from C66x CorePacs)\n"); + else + printf("(from C66x CorePacs)\n"); + } + if(ncees ==1) + { + errAddr = gpMSMC_regs->SMNCERRAR; + exception_record.status.ext_sts.info.memory.fault_address= errAddr; + + PrivID = (gpMSMC_regs->SMNCERRXR&CSL_MSMC_SMNCERRXR_SEPID_MASK) + >>CSL_MSMC_SMNCERRXR_SEPID_SHIFT; + printf("SL2 Non-correctable error occurred at address 0x%x by PrivID %d ", + errAddr, PrivID); + if(gpMSMC_regs->SMNCERRXR&CSL_MSMC_SMNCERRXR_SER_MASK) + printf("(not from C66x CorePacs)\n"); + else + printf("(from C66x CorePacs)\n"); + } + + /* clear EDC error status */ + CSL_MSMC_clearRawInterruptStatus(0, cees,ncees, cses, ncses); + + CSL_MSMC_lockNonMPAX(); +} + +/*===============================Exception=============================*/ +//data structure to save exception info +Exception_Record exception_record; + +/*some exception events routed from CIC to INTC and then to exception moduel, +all these events are routed to one input of INTC*/ +Uint32 guwIntcCICExcEvtIdx= 95; /*INTC event number mapping to CIC exception events*/ +Uint32 gCIC_EXC_out_num = 15; //CIC output event number +Uint32 gCIC_EXC_EN_MASK[8]= {0,0,0,0,0,0,0,0}; +/***************************************************************************** + Prototype : KeyStone_CIC_exception_events_mapping + Description : CIC exception event mapping to the NMI external exception + Input : void + Output : None + Return Value : + + History : + 1.Date : 2012/10/5 + Author : Brighton Feng + Modification : Created function + + 2.Date : 2012/10/20 + Author : Zhan + Modification : Add event for TCI6614 + + 3.Date : 2012/10/28 + Author : Brighton Feng +*****************************************************************************/ +void KeyStone_CIC_exception_events_mapping(void) +{ + TDSP_Board_Type DSP_Board_Type= KeyStone_Get_dsp_board_type(); + +#if 1 + if(C6670_EVM==DSP_Board_Type + ||DUAL_NYQUIST_EVM==DSP_Board_Type + ||TCI6614_EVM==DSP_Board_Type) + { + gCIC_EXC_out_num= 15+16*DNUM; + } + else if(C6678_EVM==DSP_Board_Type) + { + if(DNUM<4) + gCIC_EXC_out_num= 7+8*DNUM; + else + { + gCIC_EXC_out_num= 7+8*(DNUM-4); + gpCIC_regs= gpCIC1_regs; + } + } + else + { + puts("Unknown DSP board type!"); + return; + } +#endif + + /*-----------------------CP_INTC configuration---------------------*/ + /* Disable Global host interrupts. */ + gpCIC_regs->GLOBAL_ENABLE_HINT_REG= 0; + + /* route following system events to CIC out (event 22 of INTC), and then to exception + TCI6614, C6670, C6678: + CIC: 0 EDMA3CC1 EDMACC_ERRINT EDMA3CC1 error interrupt + CIC: 2 EDMA3CC1 EDMATC_ERRINT0 EDMA3CC1 EDMA3TC0 error interrupt + CIC: 3 EDMA3CC1 EDMATC_ERRINT1 EDMA3CC1 EDMA3TC1 error interrupt + CIC: 4 EDMA3CC1 EDMATC_ERRINT2 EDMA3CC1 EDMA3TC2 error interrupt + CIC: 5 EDMA3CC1 EDMATC_ERRINT3 EDMA3CC1 EDMA3TC3 error interrupt + CIC: 16 EDMA3CC2 EDMACC_ERRINT EDMA3CC2 error interrupt + CIC: 18 EDMA3CC2 EDMATC_ERRINT0 EDMA3CC2 EDMA3TC0 error interrupt + CIC: 19 EDMA3CC2 EDMATC_ERRINT1 EDMA3CC2 EDMA3TC1 error interrupt + CIC: 20 EDMA3CC2 EDMATC_ERRINT2 EDMA3CC2 EDMA3TC2 error interrupt + CIC: 21 EDMA3CC2 EDMATC_ERRINT3 EDMA3CC2 EDMA3TC3 error interrupt + CIC: 32 EDMA3CC0 EDMACC_ERRINT EDMA3CC0 error interrupt + CIC: 34 EDMA3CC0 EDMATC_ERRINT0 EDMA3CC0 EDMA3TC0 error interrupt + CIC: 35 EDMA3CC0 EDMATC_ERRINT1 EDMA3CC0 EDMA3TC1 error interrupt + CIC: 99 MSMC_dedc_nc_error Non-correctable soft error detected on SRAM read + CIC: 100 MSMC_scrub_nc_error Non-correctable soft error detected during scrub cycle + CIC: 102 MSMC_mpf_error8 Memory protection fault indicators for each system master PrivID + CIC: 103 MSMC_mpf_error9 Memory protection fault indicators for each system master PrivID + CIC: 104 MSMC_mpf_error10 Memory protection fault indicators for each system master PrivID + CIC: 105 MSMC_mpf_error11 Memory protection fault indicators for each system master PrivID + CIC: 106 MSMC_mpf_error12 Memory protection fault indicators for each system master PrivID + CIC: 107 MSMC_mpf_error13 Memory protection fault indicators for each system master PrivID + CIC: 108 MSMC_mpf_error14 Memory protection fault indicators for each system master PrivID + CIC: 109 MSMC_mpf_error15 Memory protection fault indicators for each system master PrivID + CIC: 110 DDR3_ERR DDR3 ECC Error Interrupt + TCI6614, C6670: + CIC: 170 MSMC_mpf_error4 Memory protection fault indicators for each system master PrivID + CIC: 171 MSMC_mpf_error5 Memory protection fault indicators for each system master PrivID + CIC: 172 MSMC_mpf_error6 Memory protection fault indicators for each system master PrivID + CIC: 173 MSMC_mpf_error7 Memory protection fault indicators for each system master PrivID + */ + KeyStone_CIC_event_map(gpCIC_regs, 0 , gCIC_EXC_out_num); + KeyStone_CIC_event_map(gpCIC_regs, 2 , gCIC_EXC_out_num); + KeyStone_CIC_event_map(gpCIC_regs, 3 , gCIC_EXC_out_num); + KeyStone_CIC_event_map(gpCIC_regs, 4 , gCIC_EXC_out_num); + KeyStone_CIC_event_map(gpCIC_regs, 5 , gCIC_EXC_out_num); + KeyStone_CIC_event_map(gpCIC_regs, 16, gCIC_EXC_out_num); + KeyStone_CIC_event_map(gpCIC_regs, 18, gCIC_EXC_out_num); + KeyStone_CIC_event_map(gpCIC_regs, 19, gCIC_EXC_out_num); + KeyStone_CIC_event_map(gpCIC_regs, 20, gCIC_EXC_out_num); + KeyStone_CIC_event_map(gpCIC_regs, 21, gCIC_EXC_out_num); + gCIC_EXC_EN_MASK[0] |= + (1<<0 ) + |(1<<2 ) + |(1<<3 ) + |(1<<4 ) + |(1<<5 ) + |(1<<16) + |(1<<18) + |(1<<19) + |(1<<20) + |(1<<21); + + KeyStone_CIC_event_map(gpCIC_regs, 32, gCIC_EXC_out_num); + KeyStone_CIC_event_map(gpCIC_regs, 34, gCIC_EXC_out_num); + KeyStone_CIC_event_map(gpCIC_regs, 35, gCIC_EXC_out_num); + gCIC_EXC_EN_MASK[1] |= + (1<<(32-32)) + |(1<<(34-32)) + |(1<<(35-32)); + + KeyStone_CIC_event_map(gpCIC_regs, 99, gCIC_EXC_out_num); + KeyStone_CIC_event_map(gpCIC_regs, 100, gCIC_EXC_out_num); + KeyStone_CIC_event_map(gpCIC_regs, 102, gCIC_EXC_out_num); + KeyStone_CIC_event_map(gpCIC_regs, 103, gCIC_EXC_out_num); + KeyStone_CIC_event_map(gpCIC_regs, 104, gCIC_EXC_out_num); + KeyStone_CIC_event_map(gpCIC_regs, 105, gCIC_EXC_out_num); + KeyStone_CIC_event_map(gpCIC_regs, 106, gCIC_EXC_out_num); + KeyStone_CIC_event_map(gpCIC_regs, 107, gCIC_EXC_out_num); + KeyStone_CIC_event_map(gpCIC_regs, 108, gCIC_EXC_out_num); + KeyStone_CIC_event_map(gpCIC_regs, 109, gCIC_EXC_out_num); + KeyStone_CIC_event_map(gpCIC_regs, 110, gCIC_EXC_out_num); + gCIC_EXC_EN_MASK[3] |= + (1<<(99 -32*3)) + |(1<<(100-32*3)) + |(1<<(102-32*3)) + |(1<<(103-32*3)) + |(1<<(104-32*3)) + |(1<<(105-32*3)) + |(1<<(106-32*3)) + |(1<<(107-32*3)) + |(1<<(108-32*3)) + |(1<<(109-32*3)) + |(1<<(110-32*3)); + + if(C6670_EVM==DSP_Board_Type + ||DUAL_NYQUIST_EVM==DSP_Board_Type + ||TCI6614_EVM==DSP_Board_Type) + { + KeyStone_CIC_event_map(gpCIC_regs, 170, gCIC_EXC_out_num); + KeyStone_CIC_event_map(gpCIC_regs, 171, gCIC_EXC_out_num); + KeyStone_CIC_event_map(gpCIC_regs, 172, gCIC_EXC_out_num); + KeyStone_CIC_event_map(gpCIC_regs, 173, gCIC_EXC_out_num); + gCIC_EXC_EN_MASK[5] |= + (1<<(170-32*5)) + |(1<<(171-32*5)) + |(1<<(172-32*5)) + |(1<<(173-32*5)); + } + + /* ----------- Mapping MPU interrupt for different chips start -----------------------*/ + if(C6670_EVM==DSP_Board_Type + ||DUAL_NYQUIST_EVM==DSP_Board_Type + ||C6678_EVM==DSP_Board_Type) + { + /* route the following system events to CIC out + CIC: 90 MPU0 addressing violation interrupt and protection violation interrupt + CIC: 92 MPU1 addressing violation interrupt and protection violation interrupt + CIC: 94 MPU2 addressing violation interrupt and protection violation interrupt + CIC: 96 MPU3 addressing violation interrupt and protection violation interrupt + */ + KeyStone_CIC_event_map(gpCIC_regs, 90, gCIC_EXC_out_num); + KeyStone_CIC_event_map(gpCIC_regs, 92, gCIC_EXC_out_num); + KeyStone_CIC_event_map(gpCIC_regs, 94, gCIC_EXC_out_num); + KeyStone_CIC_event_map(gpCIC_regs, 96, gCIC_EXC_out_num); + gCIC_EXC_EN_MASK[2] |= + (1<<(90 -32*2)) + |(1<<(92 -32*2)) + |(1<<(94 -32*2)); + gCIC_EXC_EN_MASK[3] |= + (1<<(96 -32*3)); + + /* 6618_6670 only */ + if(C6670_EVM==DSP_Board_Type + ||DUAL_NYQUIST_EVM==DSP_Board_Type) + { + /* + CIC: 174 MPU4 addressing violation interrupt and protection violation interrupt + CIC: 180 MPU5 addressing violation interrupt and protection violation interrupt + */ + KeyStone_CIC_event_map(gpCIC_regs, 174, gCIC_EXC_out_num); + KeyStone_CIC_event_map(gpCIC_regs, 180, gCIC_EXC_out_num); + gCIC_EXC_EN_MASK[5] |= + (1<<(174-32*5)) + |(1<<(180-32*5)); + } + } + + if(TCI6614_EVM==DSP_Board_Type) + { + /* route the following system events to CIC out + CIC: 23 MPU0~7 addressing violation interrupt combine output + CIC: 37 MPU0~7 protection violation interrupt combine output + */ + KeyStone_CIC_event_map(gpCIC_regs, 23, gCIC_EXC_out_num); + KeyStone_CIC_event_map(gpCIC_regs, 37, gCIC_EXC_out_num); + gCIC_EXC_EN_MASK[0] |= + (1<<23); + gCIC_EXC_EN_MASK[1] |= + (1<<(37 -32)); + + } + /* ----------- Mapping MPU interrupt for different chips end -----------------------*/ + + /* Enable Global host interrupts. */ + gpCIC_regs->GLOBAL_ENABLE_HINT_REG= 1; + +} +/***************************************************************************** + Prototype : KeyStone_Exception_cfg + Description : Config the system err and external exception to generate the NMI. + Call this function as last step after all + configuration/initialization complete + Input : Bool bGlobalExceptionMaster. If TRUE, the global exception events + from CIC will be routed to exception model of this CPU core. + Output : None + Return Value : +*****************************************************************************/ +void KeyStone_Exception_cfg(Bool bGlobalExceptionMaster) +{ + + puts("Enable Exception handling..."); + + TSCL = 0; /* Enable the TSC */ + + memset(&exception_record, 0, sizeof(exception_record)); +#if 0 + /*Clear all CPU events*/ + gpCGEM_regs->EVTCLR[0]= 0xFFFFFFFF; + gpCGEM_regs->EVTCLR[1]= 0xFFFFFFFF; + gpCGEM_regs->EVTCLR[2]= 0xFFFFFFFF; + gpCGEM_regs->EVTCLR[3]= 0xFFFFFFFF; +#endif + /*clear memory fault*/ + gpCGEM_regs->L1PMPFCR = 1; + gpCGEM_regs->L1DMPFCR = 1; + gpCGEM_regs->L2MPFCR = 1; + gpXMC_regs->XMPFCR = 1; + + /*clear configuration bus error*/ + gpCGEM_regs->ICFGMPFCR= 1; + gpCGEM_regs->ECFGERRCLR= 1; + + /* clear the MDMAERR */ + gpCGEM_regs->MDMAERRCLR = 1; + + /*clear interrupt drop staus*/ + gpCGEM_regs->INTXCLR = 1; + + gpCGEM_regs->INTDMASK= ~IER; /*only monitor drop of enabled interrupts*/ + + /*enable events: + 10 MSMC_mpf_error_n MSMC Memory protection fault caused by local CorePac + 96 INTERR Dropped CPU interrupt event + 97 EMC_IDMAERR Invalid IDMA parameters + 110 MDMAERREVT XMC VBUSM error event + 113 PMC_ED Single bit error detected during DMA accesses L1P + 117 UMC_ED2 Uncorrected bit error detected LL2 + 119 SYS_CMPA CPU Memory Protection Fault for local configuration of INTC and power control + 120 PMC_CMPA CPU memory protection fault for L1P + 121 PMC_DMPA DMA memory protection fault for L1P + 122 DMC_CMPA CPU memory protection fault for L1D (and other memory read finally goes through the L1D controller) + 123 DMC_DMPA DMA memory protection fault for L1D + 124 UMC_CMPA CPU memory protection fault for LL2 + 125 UMC_DMPA DMA memory protection fault for LL2 + 126 EMC_CMPA CPU memory protection fault for other local configuration space between 0x01000000 - 0x01BFFFFF + 127 EMC_BUSERR Bus Error Interrupt for global configuration space between 0x01C00000 - 0x07FFFFFF + */ + gpCGEM_regs->EXPMASK[0]= ~(1<EXPMASK[1]= 0xFFFFFFFF; + gpCGEM_regs->EXPMASK[2]= 0xFFFFFFFF; + gpCGEM_regs->EXPMASK[3]= ~((1<<(CSL_GEM_INTERR - 96))| + (1<<(CSL_GEM_EMC_IDMAERR-96))| + (1<<(CSL_GEM_MDMAERREVT-96))| + (1<<(CSL_GEM_PMC_ED-96))| + (1<<(CSL_GEM_UMC_ED2-96))| + (1<<(CSL_GEM_SYS_CMPA-96))| + (1<<(CSL_GEM_PMC_CMPA-96))| + (1<<(CSL_GEM_PMC_DMPA-96))| + (1<<(CSL_GEM_DMC_CMPA-96))| + (1<<(CSL_GEM_DMC_DMPA-96))| + (1<<(CSL_GEM_UMC_CMPA-96))| + (1<<(CSL_GEM_UMC_DMPA-96))| + (1<<(CSL_GEM_EMC_CMPA-96))| + (1<<(CSL_GEM_EMC_BUSERR-96))); + + + if(bGlobalExceptionMaster) + { + /*enable exception events routed from CIC, + please note, this should be only configured for one CPU*/ + KeyStone_CIC_exception_events_mapping(); + gpCGEM_regs->EXPMASK[guwIntcCICExcEvtIdx>>5] &= (~(1<<(guwIntcCICExcEvtIdx&0x1F))); + } + + /*clear exception flag*/ + ECR = EFR; + IERR = 0; + + /*Eanble external exception, global exception enable*/ + TSR = TSR| + (1<>CSL_CGEM_MDMAERR_ERR_SHIFT; + if (1==err) { + puts(" MDMA read status error detected"); + } + else if (2==err) { + puts(" MDMA write status error detected"); + } + else if (3==err) { + puts(" CFG read status error detected"); + } + else if (4==err) { + puts(" CFG write status error detected"); + } + + printf(" XID (Transaction ID)= %d\n", + (ERR_REG & CSL_CGEM_MDMAERR_XID_MASK)>>CSL_CGEM_MDMAERR_XID_SHIFT); + + stat= (ERR_REG & CSL_CGEM_MDMAERR_STAT_MASK)>>CSL_CGEM_MDMAERR_STAT_SHIFT; + printf(" %s\n", bus_err_stat_str[stat]); +} + +/***************************************************************************** + Prototype : KeyStone_CIC_EXC_handler + Description : This function handle the exception events from CIC + Input : void + Output : None + Return Value : void + + History : + 1.Date : 2012/10/18 + Author : Zhan + Modification : Created function + + 2.Date : 2012/10/28 + Author : Brighton Feng + Modification : Add EDMA error processing + +*****************************************************************************/ +void KeyStone_CIC_EXC_handler() +{ + int i; + Uint32 status[4], status5 = 0; + + TDSP_Board_Type DSP_Board_Type; + + DSP_Board_Type= KeyStone_Get_dsp_board_type(); + + /*Step1: Disable CIC host interrupt*/ + KeyStone_CIC_disable_host_int(gpCIC_regs, gCIC_EXC_out_num); + + status[0]= gpCIC_regs->ENA_STATUS_REG[0]&gCIC_EXC_EN_MASK[0]; + status[1]= gpCIC_regs->ENA_STATUS_REG[1]&gCIC_EXC_EN_MASK[1]; + status[2]= gpCIC_regs->ENA_STATUS_REG[2]&gCIC_EXC_EN_MASK[2]; + status[3]= gpCIC_regs->ENA_STATUS_REG[3]&gCIC_EXC_EN_MASK[3]; + exception_record.status.ext_sts.CIC_STATUS[0]= status[0]; + exception_record.status.ext_sts.CIC_STATUS[1]= status[1]; + exception_record.status.ext_sts.CIC_STATUS[2]= status[2]; + exception_record.status.ext_sts.CIC_STATUS[3]= status[3]; + + /*Step2: clear system events*/ + gpCIC_regs->ENA_STATUS_REG[0]= status[0]; + gpCIC_regs->ENA_STATUS_REG[1]= status[1]; + gpCIC_regs->ENA_STATUS_REG[2]= status[2]; + gpCIC_regs->ENA_STATUS_REG[3]= status[3]; + + /* The different device INTC number is different, if read the non-exist space will + trigger the L1D memory protection error. + */ + if((C6670_EVM == DSP_Board_Type) + ||(DUAL_NYQUIST_EVM == DSP_Board_Type) + ||(TCI6614_EVM == DSP_Board_Type)) + { + status5 = gpCIC_regs->ENA_STATUS_REG[5]&gCIC_EXC_EN_MASK[5]; + exception_record.status.ext_sts.CIC_STATUS[5]= status5; + + /*Step2: clear system events*/ + gpCIC_regs->ENA_STATUS_REG[5]= status5 ; + } + + /*----------------------------EDMA error-----------------------------*/ + /* + CIC: 0 EDMA3CC1 EDMACC_ERRINT EDMA3CC1 error interrupt + CIC: 2 EDMA3CC1 EDMATC_ERRINT0 EDMA3CC1 EDMA3TC0 error interrupt + CIC: 3 EDMA3CC1 EDMATC_ERRINT1 EDMA3CC1 EDMA3TC1 error interrupt + CIC: 4 EDMA3CC1 EDMATC_ERRINT2 EDMA3CC1 EDMA3TC2 error interrupt + CIC: 5 EDMA3CC1 EDMATC_ERRINT3 EDMA3CC1 EDMA3TC3 error interrupt*/ + if(status[0]&0x3D) + EDMA_error_handler(1, status[0]&0x3D); + + /* + CIC: 16 EDMA3CC2 EDMACC_ERRINT EDMA3CC2 error interrupt + CIC: 18 EDMA3CC2 EDMATC_ERRINT0 EDMA3CC2 EDMA3TC0 error interrupt + CIC: 19 EDMA3CC2 EDMATC_ERRINT1 EDMA3CC2 EDMA3TC1 error interrupt + CIC: 20 EDMA3CC2 EDMATC_ERRINT2 EDMA3CC2 EDMA3TC2 error interrupt + CIC: 21 EDMA3CC2 EDMATC_ERRINT3 EDMA3CC2 EDMA3TC3 error interrupt*/ + if((status[0]>>16)&0x3D) + EDMA_error_handler(2, (status[0]>>16)&0x3D); + + /* + CIC: 32 EDMA3CC0 EDMACC_ERRINT EDMA3CC0 error interrupt + CIC: 34 EDMA3CC0 EDMATC_ERRINT0 EDMA3CC0 EDMA3TC0 error interrupt + CIC: 35 EDMA3CC0 EDMATC_ERRINT1 EDMA3CC0 EDMA3TC1 error interrupt*/ + if(status[1]&0xD) + EDMA_error_handler(0, status[1]&0xD); + + /*----------------------------MPU error-----------------------------*/ + if(TCI6614_EVM == DSP_Board_Type) + { + //CIC: 23 MPU0~7 addressing violation interrupt combine output + //CIC: 37 MPU0~7 protection violation interrupt combine output + if((status[0]&(1<<23))||(status[1]&(1<<(37-32)))) + { + for(i=0; i<8; i++) + { + /*MPU5 (for BCP) of TCI6614 is only accessible + when BCP is enabled through PSC*/ + if((5==i)&& + ((CSL_PSC_getPowerDomainState(5) != PSC_PDSTATE_ON) || + (CSL_PSC_getModuleState (12) != PSC_MODSTATE_ENABLE))) + continue; + + if(gpMPU_regs[i]->INT_RAW_STATUS_SET & 0x3) + { + KeyStone_peripherals_MPU_excepiton_handler(i); + } + } + + /*The MPU events in TCI6614 are different from other KeyStone + devices. All the MPU0~7 events are combined into single event + and connected to the CIC0 as one system event. + We have to clear the MPU event flag at the source level first + and then are able to clear the CIC flags because the INTD for the + MPU events is for the combination purpose but do not convert + the level interrupt to pulse.*/ + /*clear system events*/ + gpCIC_regs->ENA_STATUS_REG[0]= status[0]; + gpCIC_regs->ENA_STATUS_REG[1]= status[1]; + } + } + else + { + //CIC: 90 MPU0 addressing violation interrupt and protection violation interrupt + if(status[2]&(1<<(90-64))) + { + KeyStone_peripherals_MPU_excepiton_handler(0); + } + //CIC: 92 MPU1 addressing violation interrupt and protection violation interrupt + if(status[2]&(1<<(92-64))) + { + KeyStone_peripherals_MPU_excepiton_handler(1); + } + //CIC: 94 MPU2 addressing violation interrupt and protection violation interrupt + if(status[2]&(1<<(94-64))) + { + KeyStone_peripherals_MPU_excepiton_handler(2); + } + //CIC: 96 MPU3 addressing violation interrupt and protection violation interrupt + if(status[3]&(1<<(96-96))) + { + KeyStone_peripherals_MPU_excepiton_handler(3); + } + + if((C6670_EVM == DSP_Board_Type) + ||(DUAL_NYQUIST_EVM == DSP_Board_Type)) + { + //CIC: 174 MPU4 addressing violation interrupt and protection violation interrupt + //CIC: 180 MPU5 addressing violation interrupt and protection violation interrupt + if(status5&(1<<(174-160))) + { + KeyStone_peripherals_MPU_excepiton_handler(4); + } + if(status5&(1<<(180-160))) + { + KeyStone_peripherals_MPU_excepiton_handler(5); + } + } + } + + /*----------------------------MSMC error-----------------------------*/ + //CIC: 99 MSMC_dedc_nc_error Non-correctable (2-bit) soft error detected on SRAM read + if(status[3]&(1<<(99-96))) + { + KeyStone_SL2_EDC_handler(); + } + //CIC: 100 MSMC_scrub_nc_error Non-correctable (2-bit) soft error detected during scrub cycle + if(status[3]&(1<<(100-96))) + { + KeyStone_SL2_EDC_handler(); + } + + /* + CIC: 102 MSMC_mpf_error8 Memory protection fault indicators for each system master PrivID + CIC: 103 MSMC_mpf_error9 Memory protection fault indicators for each system master PrivID + CIC: 104 MSMC_mpf_error10 Memory protection fault indicators for each system master PrivID + CIC: 105 MSMC_mpf_error11 Memory protection fault indicators for each system master PrivID + CIC: 106 MSMC_mpf_error12 Memory protection fault indicators for each system master PrivID + CIC: 107 MSMC_mpf_error13 Memory protection fault indicators for each system master PrivID + CIC: 108 MSMC_mpf_error14 Memory protection fault indicators for each system master PrivID + CIC: 109 MSMC_mpf_error15 Memory protection fault indicators for each system master PrivID*/ + if((status[3]>>(102-96))&0xFF) + KeyStone_MSMC_protection_exception_handler(); + + if((C6670_EVM == DSP_Board_Type) + ||(DUAL_NYQUIST_EVM == DSP_Board_Type) + ||(TCI6614_EVM == DSP_Board_Type)) + { + /* + CIC: 170 MSMC_mpf_error4 Memory protection fault indicators for each system master PrivID + CIC: 171 MSMC_mpf_error5 Memory protection fault indicators for each system master PrivID + CIC: 172 MSMC_mpf_error6 Memory protection fault indicators for each system master PrivID + CIC: 173 MSMC_mpf_error7 Memory protection fault indicators for each system master PrivID*/ + if((status5>>(170-160))&0xF) + KeyStone_MSMC_protection_exception_handler(); + + } + + /*----------------------------DDR ECC error-------------------------*/ + //CIC: 110 DDR3_ERR DDR3_EMIF Error Interrupt + if(status[3]&(1<<(110-96))) + { + printf(" DDR ECC error happened during "); + + exception_record.status.ext_sts.info.memory.fault_status.DDR_IRQSTATUS_SYS= + gpDDR_regs->IRQSTATUS_SYS; + + if(gpDDR_regs->IRQSTATUS_SYS&CSL_EMIF4F_IRQSTATUS_SYS_REG_RD_ECC_ERR_SYS_MASK) + printf("read "); + if(gpDDR_regs->IRQSTATUS_SYS&CSL_EMIF4F_IRQSTATUS_SYS_REG_WR_ECC_ERR_SYS_MASK) + printf("write "); + printf(".\n"); + + //clear the status + gpDDR_regs->IRQSTATUS_SYS= CSL_EMIF4F_IRQSTATUS_SYS_REG_RD_ECC_ERR_SYS_MASK + |CSL_EMIF4F_IRQSTATUS_SYS_REG_WR_ECC_ERR_SYS_MASK; + } + + /*Step3: Enable the CIC host interrupt */ + KeyStone_CIC_enable_host_int(gpCIC_regs, gCIC_EXC_out_num); + +} + +/***************************************************************************** + Prototype : KeyStone_EXC_external + Description : external exception processing + Input : void + Output : None + Return Value : + + History : + 1.Date : 2010/12/12 + Author : Brighton Feng + Modification : Created function +*****************************************************************************/ +void KeyStone_EXC_external(void) +{ + int i; + unsigned int INTXSTAT, flag[4]; + + for(i= 0; i<4; i++) + { + flag[i] = gpCGEM_regs->MEXPFLAG[i]; + if(flag[i]) + { + exception_record.status.ext_sts.MEXPFLAG[i]= flag[i]; + printf("External exception happened. MEXPFLAG[%d]=0x%x.\n", + i, flag[i]); + gpCGEM_regs->EVTCLR[i] = flag[i]; + } + } + + if(0 == (flag[0]|flag[1]|flag[2]|flag[3])) + { + puts("Enter external Exception service routine, but external excpetion flage is 0!"); + return; + } + + /*Exception events routed from CIC*/ + if(flag[guwIntcCICExcEvtIdx>>5] & (1<<(guwIntcCICExcEvtIdx&0x1F))) + { + KeyStone_CIC_EXC_handler(); + } + + /*MSMC memory protection exception*/ + if(flag[0]&(1<INTXSTAT; + exception_record.status.ext_sts.info.INTXSTAT= INTXSTAT; + + if(INTXSTAT&CSL_CGEM_INTXSTAT_DROP_MASK) + printf(" Event 96: DSP Interrupt %d (INTC input Event %d) dropped\n", + (INTXSTAT&CSL_CGEM_INTXSTAT_CPUINT_MASK)>>CSL_CGEM_INTXSTAT_CPUINT_SHIFT, + (INTXSTAT&CSL_CGEM_INTXSTAT_SYSINT_MASK)>>CSL_CGEM_INTXSTAT_SYSINT_SHIFT); + } + + if(flag[3]&(1<<(CSL_GEM_EMC_IDMAERR-96))) + puts(" Event 97: EMC_IDMAERR Invalid IDMA parameters"); + + /*MDMA XMC VBUSM error*/ + if(flag[3]&(1<<(CSL_GEM_MDMAERREVT-96))) + { + puts(" Event 110: MDMAERREVT XMC VBUSM error event"); + if(gpXMC_regs->XMPFSR) + { + /*XMC protection error*/ + memory_protection_exception_handler(gpXMC_regs->XMPFAR, gpXMC_regs->XMPFSR); + gpXMC_regs->XMPFCR = 1; + } + else + { + /*other VBUSM error*/ + Bus_error_handler(gpCGEM_regs->MDMAERR); + } + /* clear the MDMAERR */ + gpCGEM_regs->MDMAERRCLR = 1; + } + + /*L1P Single bit error detected during DMA read*/ + if(flag[3]&(1<<(CSL_GEM_PMC_ED-96))) + { + puts(" Event 113: PMC_ED Single bit error detected during DMA read"); + L1P_ED_handler(); + } + + /*LL2 Uncorrected bit error detected*/ + if(flag[3]&(1<<(CSL_GEM_UMC_ED2-96))) + { + puts(" Event 117: UMC_ED2 Uncorrected bit error detected"); + LL2_EDC_handler(FALSE); + } + + /*local register memory protection exception*/ + if(flag[3]&(1<<(CSL_GEM_SYS_CMPA-96))) + { + puts(" Event 119: SYS_CMPA CPU Memory Protection Fault for local configuration of INTC and power control"); + } + + /*L1P memory protection exception*/ + if(flag[3]&(3<<(CSL_GEM_PMC_CMPA-96))) + { + if(flag[3]&(1<<(CSL_GEM_PMC_CMPA-96))) + puts(" Event 120: PMC_CMPA CPU memory protection fault for L1P"); + if(flag[3]&(1<<(CSL_GEM_PMC_DMPA-96))) + puts(" Event 121: PMC_DMPA DMA memory protection fault for L1P"); + memory_protection_exception_handler(gpCGEM_regs->L1PMPFAR, gpCGEM_regs->L1PMPFSR); + gpCGEM_regs->L1PMPFCR = 1; + } + + /*L1D memory protection exception*/ + if(flag[3]&(3<<(CSL_GEM_DMC_CMPA-96))) + { + if(flag[3]&(1<<(CSL_GEM_DMC_CMPA-96))) + puts(" Event 122: DMC_CMPA CPU memory protection fault for L1D (and other memory read finally goes through the L1D controller)"); + if(flag[3]&(1<<(CSL_GEM_DMC_DMPA-96))) + puts(" Event 123: DMC_DMPA DMA memory protection fault for L1D"); + memory_protection_exception_handler(gpCGEM_regs->L1DMPFAR, gpCGEM_regs->L1DMPFSR); + gpCGEM_regs->L1DMPFCR = 1; + } + + /*LL2 memory protection exception*/ + if(flag[3]&(3<<(CSL_GEM_UMC_CMPA-96))) + { + if(flag[3]&(1<<(CSL_GEM_UMC_CMPA-96))) + puts(" Event 124: UMC_CMPA CPU memory protection fault for L2 "); + if(flag[3]&(1<<(CSL_GEM_UMC_DMPA-96))) + puts(" Event 125: UMC_DMPA DMA memory protection fault for L2 "); + memory_protection_exception_handler(gpCGEM_regs->L2MPFAR, gpCGEM_regs->L2MPFSR); + gpCGEM_regs->L2MPFCR = 1; + } + + /*local registers protection exception*/ + if(flag[3]&(1<<(CSL_GEM_EMC_CMPA-96))) + { + puts(" Event 126: EMC_CMPA CPU memory protection fault for local configuration space between 0x01000000-0x01BFFFFF"); + memory_protection_exception_handler(gpCGEM_regs->ICFGMPFAR, gpCGEM_regs->ICFGMPFSR); + gpCGEM_regs->ICFGMPFCR= 1; + } + + /*external configuration bus error*/ + if(flag[3]&(Uint32)(1<<(CSL_GEM_EMC_BUSERR-96))) + { + puts(" Event 127: EMC_BUSERR Bus Error Interrupt for global configuration space between 0x01C00000 - 0x07FFFFFF"); + Bus_error_handler(gpCGEM_regs->ECFGERR); + gpCGEM_regs->ECFGERRCLR= 1; + } +} + +char * internal_exception_str[]= +{ + "Instruction fetch exception", + "Fetch packet exception", + "Execute packet exception", + "Opcode exception", + "Resource conflict exception", + "Resource access exception", + "Privilege exception", + "SPLOOP buffer exception", + "Missed stall exception" +}; + +/***************************************************************************** + Prototype : EXC_internal + Description : internal exception handler + Input : void + Output : None + Return Value : + + History : + 1.Date : 2010/12/12 + Author : Brighton Feng + Modification : Created function + +*****************************************************************************/ +/*internal exception handler*/ +void EXC_internal(void) +{ + int i; + unsigned int ierr; + + /*record IERR */ + ierr = IERR; + exception_record.status.IERR= ierr; + + if(ierr) + { + /*Clear internal excpeiton flag*/ + IERR= 0; + + printf("internal excpetion happened. IERR=0x%x.\n", ierr); + for(i=0; i<9; i++) + { + if((ierr>>i)&1) + printf(" %s\n", internal_exception_str[i]); + } + if (ierr & CSL_CHIP_IERR_IFX_MASK) { + /* L1P EDC Processing*/ + L1P_ED_handler(); + } + } + else + puts("Enter Internal Exception service routine, but internal excpetion flage is 0!"); + +} +/***************************************************************************** + Prototype : EXC_nmi + Description : NMI processing + Input : void + Output : None + Return Value : + + History : + 1.Date : 2010/12/12 + Author : Brighton Feng + Modification : Created function + +*****************************************************************************/ +void EXC_NMI(void) +{ + puts("NMI exception happened, normally you should reset the DSP to recover from the problem!"); +} + +/***************************************************************************** + Prototype : EXC_swgen + Description : software generated exception handler + Input : void + Output : None + Return Value : +*****************************************************************************/ +void EXC_swgen(void) +{ + puts("Software generated exception happened."); +} + +/***************************************************************************** + Prototype : Exception_service_routine + Description : Exception service routine + Input : void + Output : None + Return Value : + + History : + 1.Date : 2010/12/12 + Author : Brighton Feng + Modification : Created function + +*****************************************************************************/ +#pragma NMI_INTERRUPT( Exception_service_routine ); +void Exception_service_routine(void) +{ + unsigned int efr, nrp, ntsr, tscl, tsch, irp, itsr; + + /*record timestamp*/ + tscl = TSCL; + exception_record.TSCL= tscl; + tsch = TSCH; + exception_record.TSCH= tsch; + + nrp = NRP; /*record NRP */ + exception_record.NRP= nrp; + ntsr = NTSR; /*record NTSR */ + exception_record.NTSR= ntsr; + efr = EFR; /*record EFR */ + exception_record.EFR= efr; + + irp = IRP; /*record IRP */ + itsr = ITSR; /*record ITSR */ + exception_record.IRP= irp; + exception_record.ITSR= itsr; + + if(efr) + { + /*Clear excpeiton flag*/ + ECR = efr; + + /*check all possible exceptions*/ + if (efr & CSL_CHIP_EFR_OXF_MASK) { + /* S/W generated exception */ + EXC_swgen(); + } + if (efr & CSL_CHIP_EFR_IXF_MASK) { + /* internal exception */ + EXC_internal(); + } + if (efr & CSL_CHIP_EFR_EXF_MASK) { + /* external exception */ + KeyStone_EXC_external(); + } + if (efr & CSL_CHIP_EFR_NXF_MASK) { + /* legacy NMI exception */ + EXC_NMI(); + } + } + else + puts("Enter Exception service routine, but excpetion flage is 0!"); + + printf("NRP=0x%x, NTSR=0x%x, IRP=0x%x, ITSR=0x%x, TSCH= 0x%x, TSCL= 0x%x\n", + nrp, ntsr, irp, itsr, tsch, tscl); + + printf(" B3=0x%x, A4=0x%x, B4= 0x%x, B14= 0x%x, B15= 0x%x\n", + exception_record.B3, exception_record.A4, + exception_record.B4, exception_record.B14, + exception_record.B15); + + /* + It is not always possible to safely exit the exception handling routine. Conditions that + can prevent a safe return from exceptions include: + 1. SPLOOPs that are terminated by an exception cannot be resumed correctly. The + SPLX bit in NTSR should be verified to be 0 before returning. + 2. Exceptions that occur when interrupts are blocked cannot be resumed correctly. + The IB bit in NTSR should be verified to be 0 before returning. + 3. Exceptions that occur at any point in the code that cannot be interrupted safely + (for example, a tight loop containing multiple assignments) cannot be safely + returned to. The compiler will normally disable interrupts at these points in the + program; check the GIE bit in NTSR to be 1 to verify that this condition is met. + 4. NRP is not in valid address space*/ + if((ntsr&CSL_CHIP_TSR_SPLX_MASK) + ||(ntsr&CSL_CHIP_TSR_IB_MASK) + ||(0==(ntsr&CSL_CHIP_TSR_GIE_MASK)) + ||(0x800000>NRP)) + { + puts("Exception happened at a place can not safely return!"); + //while(1); //trap + exit(0); + } + +} + +/***************************************************************************** + Prototype : Nested_Exception_service_routine + Description : Nested Exception service routine + When a non-maskable exception happens in the first exception service routine, + then the reset vector is used when redirecting program execution to service the second + exception. In this case, NTSR and NRP are left unchanged. TSR is copied to ITSR and + the current PC is copied to IRP. TSR is set to the default exception processing value and + the NMIE bit in IER is cleared in this case preventing any further external exceptions. + Input : void + Output : None + Return Value : + + History : + 1.Date : 2010/12/29 + Author : Brighton Feng + Modification : Created function + +*****************************************************************************/ +interrupt void Nested_Exception_service_routine(void) +{ + unsigned int tscl, tsch; + + /*record timestamp*/ + tscl = TSCL; + tsch = TSCH; + + if(0==exception_record.TSCL) + exception_record.TSCL= tscl; + if(0==exception_record.TSCH) + exception_record.TSCH= tsch; + if(0==exception_record.NRP) + exception_record.NRP= NRP; + if(0==exception_record.NTSR) + exception_record.NTSR= NTSR; + if(0==exception_record.EFR) + exception_record.EFR= EFR; + if(0==exception_record.status.IERR) + exception_record.status.IERR= IERR; + + exception_record.IRP= IRP; + exception_record.ITSR= ITSR; + + printf("Nested exception happened! IRP=0x%x, ITSR=0x%x\n", + IRP, ITSR); + + printf("NRP=0x%x, NTSR=0x%x, EFR=0x%x, IERR=0x%x, TSCH= 0x%x, TSCL= 0x%x\n", + NRP, NTSR, EFR, IERR, tsch, tscl); + + while(1); //trap +// exit(0); +} + +/*=========================other utility functions==========================*/ +/*clear all interrupt flag/status, setup ISTP to begining of LL2*/ +void CPU_interrupt_init() +{ + //clear interrupt and excpetion events + ICR = IFR; + ECR = EFR; + IER= 3; //disable all interrupts + + /* disable event combine */ + gpCGEM_regs->EVTMASK[0] = 0xffffffff; + gpCGEM_regs->EVTMASK[1] = 0xffffffff; + gpCGEM_regs->EVTMASK[2] = 0xffffffff; + gpCGEM_regs->EVTMASK[3] = 0xffffffff; + + /*Clear all CPU events*/ + gpCGEM_regs->EVTCLR[0]= 0xFFFFFFFF; + gpCGEM_regs->EVTCLR[1]= 0xFFFFFFFF; + gpCGEM_regs->EVTCLR[2]= 0xFFFFFFFF; + gpCGEM_regs->EVTCLR[3]= 0xFFFFFFFF; + + /*Interrupt Service Table Pointer to begining of LL2 memory*/ + ISTP= 0x800000; +} + +/*enable interrupt to CPU: IER |= uiIER_en_mask; GIE=1*/ +void CPU_interrupt_enable(Uint32 uiIER_en_mask) +{ + ICR= uiIER_en_mask; + IER |= uiIER_en_mask; + + //enable GIE + TSR = TSR|1; +} + +/***************************************************************************** + Prototype : KeyStone_get_device_info + Description : Get device information + Input : None + Output : None + Return Value : + + History : + 1.Date : 2010/12/12 + Author : Brighton Feng + Modification : Created function + 2.Date : 2014/12/2 + Author : Brighton Feng + Modification : Update to parser device type, boot mode, endian information, + speed grade, required CVDD + +*****************************************************************************/ +//get device speed grade from the EFUSE register +void KeyStone_get_device_speed_grade() +{ + Uint32 uiDevSpeed, uiSpeedCode; + + uiSpeedCode= (DEVSPEED&DEVSPEED_DSP_SPEED_MASK)>>DEVSPEED_DSP_SPEED_SHIFT; + + if(uiSpeedCode&DEVSPEED_800_MHZ_MASK_H) uiDevSpeed= 800; + else if(uiSpeedCode&DEVSPEED_1000_MHZ_MASK_H) uiDevSpeed= 1000; + else if(uiSpeedCode&DEVSPEED_1200_MHZ_MASK_H) uiDevSpeed= 1200; + else if(uiSpeedCode&DEVSPEED_1250_MHZ_MASK_H) uiDevSpeed= 1250; + else if(uiSpeedCode&DEVSPEED_1400_MHZ_MASK_H) uiDevSpeed= 1400; + else if(uiSpeedCode&DEVSPEED_1400_MHZ_MASK_L) uiDevSpeed= 1400; + else if(uiSpeedCode&DEVSPEED_1250_MHZ_MASK_L) uiDevSpeed= 1250; + else if(uiSpeedCode&DEVSPEED_1200_MHZ_MASK_L) uiDevSpeed= 1200; + else if(uiSpeedCode&DEVSPEED_1000_MHZ_MASK_L) uiDevSpeed= 1000; + else uiDevSpeed= 800; + + printf("Device speed grade = %dMHz.\n", uiDevSpeed); +} + +char * device_type_str[]= +{ + "TCI6616", + "C6670/TCI6618", + "C6678/TCI6608", + "TCI6614", + "unknown" +}; +char * endian_str[]= +{ + "big", + "little" +}; +char * boot_mode_str[]= +{ + "No boot or EMIF16(NOR FLASH) or UART", + "Serial Rapid I/O", + "Ethernet (SGMII)", + "Ethernet (SGMII) or NAND FLASH", + "PCIE", + "I2C", + "SPI", + "HyperLink" + }; +char * input_clk_str[]= +{ + "50MHz", + "66.67MHz", + "80MHz", + "100MHz", + "156.25MHz", + "250MHz", + "312.5MHz", + "122.88MHz", + "bypassed" +}; +void KeyStone_get_device_info() +{ + char * boot_mode; + Uint8 ucBootMode, ucBootMaster; + Uint32 uiVID; + Uint8 ucPLL_cfg= 8; //8 means bypassed + Uint32 * DieID= (Uint32 *)&gpBootCfgRegs->DIE_ID_REG0; + Uint32 uiJTAG_ID = gpBootCfgRegs->DEVICE_ID_REG0; + Uint32 uiDevStat = gpBootCfgRegs->BOOT_REG0; + + gDSP_board_type=KeyStone_Get_dsp_board_type(); + + ucBootMode= (uiDevStat&DEVSTAT_BOOTMODE_MASK)>>DEVSTAT_BOOTMODE_SHIFT; + ucBootMaster= (uiDevStat&DEVSTAT_BOOTMASTER_MASK)>>DEVSTAT_BOOTMASTER_SHIFT; + + if((TCI6614_EVM==gDSP_board_type)&&(1==ucBootMaster)) + { + boot_mode= "ARM"; //ARM boot + } + else + boot_mode= boot_mode_str[ucBootMode]; + + //PLL is not configured with SPI and I2C master boot mode + if((5!=ucBootMode)&&(6!=ucBootMode)) + ucPLL_cfg= (uiDevStat&DEVSTAT_SYSPLL_MASK)>>DEVSTAT_SYSPLL_SHIFT; + + printf("JTAG ID= 0x%08x. This is %s device, version variant = %d.\n", uiJTAG_ID, + device_type_str[gDSP_board_type], uiJTAG_ID>>28); + + printf("DEVSTAT= 0x%08x. %s endian, %s boot, PLL configuration implies the input clock for core is %s.\n", + uiDevStat, endian_str[uiDevStat&DEVSTAT_LENDIAN_MASK], boot_mode, + input_clk_str[ucPLL_cfg]); + + uiVID= (gpPSC_regs->VCNTLID&CSL_PSC_VCNTLID_VCNTL_MASK)>>CSL_PSC_VCNTLID_VCNTL_SHIFT; + printf("SmartReflex VID= %d, required core voltage= %.3fV.\n", uiVID, 0.7+(float)uiVID*0.41/64.f); + + printf("Die ID= 0x%08x, 0x%08x, 0x%08x, 0x%08x\n", DieID[0], DieID[1], DieID[2], DieID[3]); + + KeyStone_get_device_speed_grade(); +} +/***************************************************************************** + Prototype : KeyStone_common_device_init + Description : common initialization for internal modules in K2 device + enable memory protection interrupts, EDC for MSMC RAM + History : + 1.Date : July 11, 2014 + Author : Brighton Feng + Modification : Created function +*****************************************************************************/ +void KeyStone_common_device_init() +{ + int i; + KeyStone_get_device_info(); + + /* enable common MPU interrupts */ + for(i=0; i<4; i++) + { + KeyStone_MPU_interrupt_enable(i); + } + + /*Enable MSMC EDC and setup scrubbing cycle counter= 255*1024*/ + KeyStone_SL2_EDC_enable(255); +} + +/***************************************************************************** + Prototype : KeyStone_common_CPU_init + Description : common initialization for internal modules in K2 device + enable TSC, EDC for local RAM; clear cache; protect L1 as cache + History : + 1.Date : September 1, 2014 + Author : Brighton Feng + Modification : Created function +*****************************************************************************/ +void KeyStone_common_CPU_init() +{ + TSC_init(); //initialize TSC to measure cycle + + /*clear all interrupt flag/status, setup ISTP to begining of LL2*/ + CPU_interrupt_init(); + + /*clean cache from previous run, not required from power on or cold reset*/ + CACHE_wbInvAllL2(CACHE_WAIT); + CSL_XMC_invalidatePrefetchBuffer(); + _mfence(); + _mfence(); + + /* protect L1 as cache */ + L1_cache_protection(); + + //Enable MSMC Memory protection error interrupt for local core, refer to MSMC user guide section3.8 + KeyStone_MSMC_MP_interrupt_en(1< +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/*----------------------PLL registers definition----------------*/ +#define PLLCTL0_PLLD_SHIFT (0) +#define PLLCTL0_PLLD_MASK (0x3F<>4) | 0x80000000) + +/*max number in two numbers*/ +#define MAX(a, b) (a>b?a:b) +/*min number in two numbers*/ +#define MIN(a, b) (a0xFFFF*4) + byteCnt= 0xFFFF*4; + if((Uint32)blockPtr>=0x0C000000&&(Uint32)blockPtr<0x0D000000) //SL2 + { + CACHE_invL1d((void *)blockPtr, byteCnt, CACHE_WAIT); + CSL_XMC_invalidatePrefetchBuffer(); + } + else if((Uint32)blockPtr>=0x10000000) //DDR or other cores + { + CACHE_invL2((void *)blockPtr, byteCnt, CACHE_WAIT); + CSL_XMC_invalidatePrefetchBuffer(); + } + _mfence(); + _mfence(); + +#if CACHE_DISABLE_INT +/*workaround for the "L2 Cache Corruption During Block and Global Coherence Operations +Issue" described in errata of some devices*/ + asm(" nop 8"); + asm(" nop 8"); + _restore_interrupts(uiOldGIE); //restore interrupt +#endif +} + +static inline void WritebackCache(void * blockPtr, Uint32 byteCnt) +{ + if(byteCnt>0xFFFF*4) + byteCnt= 0xFFFF*4; + if((Uint32)blockPtr>=0x0C000000&&(Uint32)blockPtr<0x0D000000) //SL2 + { + CACHE_wbL1d((void *)blockPtr, byteCnt, CACHE_WAIT); + } + else if((Uint32)blockPtr>=0x10000000) //DDR or other cores + { + CACHE_wbL2((void *)blockPtr, byteCnt, CACHE_WAIT); + } + _mfence(); + _mfence(); +} + +static inline void WritebackAllCache(void * blockPtr) +{ + if((Uint32)blockPtr>=0x0C000000&&(Uint32)blockPtr<0x0D000000) //SL2 + { + CACHE_wbAllL1d(CACHE_WAIT);; + } + else if((Uint32)blockPtr>=0x10000000) //DDR or other cores + { + CACHE_wbAllL2(CACHE_WAIT); + } + _mfence(); + _mfence(); +} + +static inline void WritebackInvalidCache(void * blockPtr, Uint32 byteCnt) +{ +#if CACHE_DISABLE_INT +/*workaround for the "L2 Cache Corruption During Block and Global Coherence Operations +Issue" described in errata of some devices*/ + Uint32 uiOldGIE= _disable_interrupts(); +#endif + + if(byteCnt>0xFFFF*4) + byteCnt= 0xFFFF*4; + if((Uint32)blockPtr>=0x0C000000&&(Uint32)blockPtr<0x0D000000) //SL2 + { + CACHE_wbInvL1d((void *)blockPtr, byteCnt, CACHE_WAIT); + CSL_XMC_invalidatePrefetchBuffer(); + } + else if((Uint32)blockPtr>=0x10000000) //DDR or other cores + { + CACHE_wbInvL2((void *)blockPtr, byteCnt, CACHE_WAIT); + CSL_XMC_invalidatePrefetchBuffer(); + } + _mfence(); + _mfence(); + +#if CACHE_DISABLE_INT +/*workaround for the "L2 Cache Corruption During Block and Global Coherence Operations +Issue" described in errata of some devices*/ + asm(" nop 8"); + asm(" nop 8"); + _restore_interrupts(uiOldGIE); //restore interrupt +#endif +} + +static inline void WritebackInvalidAllCache(void * blockPtr) +{ +#if CACHE_DISABLE_INT +/*workaround for the "L2 Cache Corruption During Block and Global Coherence Operations +Issue" described in errata of some devices*/ + Uint32 uiOldGIE= _disable_interrupts(); +#endif + + if((Uint32)blockPtr>=0x0C000000&&(Uint32)blockPtr<0x0D000000) //SL2 + { + CACHE_wbInvAllL1d(CACHE_WAIT);//CACHE_invL1d((void *)blockPtr, byteCnt, CACHE_WAIT); + CSL_XMC_invalidatePrefetchBuffer(); + } + else if((Uint32)blockPtr>=0x10000000) //DDR or other cores + { + //CACHE_invL2((void *)blockPtr, byteCnt, CACHE_WAIT); + CACHE_wbInvAllL2(CACHE_WAIT); + CSL_XMC_invalidatePrefetchBuffer(); + } + _mfence(); + _mfence(); + +#if CACHE_DISABLE_INT +/*workaround for the "L2 Cache Corruption During Block and Global Coherence Operations +Issue" described in errata of some devices*/ + asm(" nop 8"); + asm(" nop 8"); + _restore_interrupts(uiOldGIE); //restore interrupt +#endif +} + +static inline unsigned int SWAP_ENDIAN(unsigned int byte_index) +{ +#ifdef _BIG_ENDIAN + return ((byte_index&0xFFFFFFFC)+(3-byte_index&3)); +#else + return byte_index; +#endif +} + +static inline void KeyStone_CIC_clear_system_event(CSL_CPINTCRegs* cpIntcRegs, + int input_event_num) +{ + volatile Uint32 dummy_value; + + /*clear input interrupts events*/ + cpIntcRegs->STATUS_CLR_INDEX_REG= input_event_num; + + /*dummy read to make sure the previous write data land into the register*/ + dummy_value= cpIntcRegs->STATUS_CLR_INDEX_REG; +} + +static inline void KeyStone_CIC_disable_host_int(CSL_CPINTCRegs* cpIntcRegs, + int host_int_num) +{ + volatile Uint32 dummy_value; + + /* Disable the host interrupt */ + cpIntcRegs->HINT_ENABLE_CLR_INDEX_REG = host_int_num; + + /*dummy read to make sure the previous write data land into the register*/ + dummy_value= cpIntcRegs->HINT_ENABLE_CLR_INDEX_REG; +} + +static inline void KeyStone_CIC_enable_host_int(CSL_CPINTCRegs* cpIntcRegs, + int host_int_num) +{ + volatile Uint32 dummy_value; + + /* Enable the host interrupt */ + cpIntcRegs->HINT_ENABLE_SET_INDEX_REG = host_int_num; + + /*dummy read to make sure the previous write data land into the register*/ + dummy_value= cpIntcRegs->HINT_ENABLE_SET_INDEX_REG; +} + +static inline void KeyStone_CIC_event_map(CSL_CPINTCRegs* cpIntcRegs, + int input_event_num, int out_num) +{ + /*Map input event to output*/ + cpIntcRegs->CH_MAP[SWAP_ENDIAN(input_event_num)]= out_num; + + /*clear input interrupts events*/ + cpIntcRegs->STATUS_CLR_INDEX_REG= input_event_num; + + /*enable input interrupts events*/ + cpIntcRegs->ENABLE_SET_INDEX_REG= input_event_num; + + /*enable output*/ + cpIntcRegs->HINT_ENABLE_SET_INDEX_REG= out_num; +} + + +typedef enum +{ + DUAL_NYQUIST_EVM = 0, + C6670_EVM, + C6678_EVM, + TCI6614_EVM, + C6657_EVM, + UNKNOWN +}TDSP_Board_Type; + +extern TDSP_Board_Type gDSP_board_type; + +static inline TDSP_Board_Type KeyStone_Get_dsp_board_type() +{ + Uint32 deviceID= gpBootCfgRegs->DEVICE_ID_REG0&0x0FFFFFFF; + + gDSP_board_type= UNKNOWN; + if(0x0009D02F == deviceID) + gDSP_board_type= DUAL_NYQUIST_EVM; + if(0x0B94102F == deviceID) + { + gDSP_board_type= C6670_EVM; + //DSP_Board_Type= DUAL_NYQUIST_EVM; + } + if(0x0009E02F == deviceID) + gDSP_board_type= C6678_EVM; + if(0x0B96202F == deviceID) + gDSP_board_type= TCI6614_EVM; + if(0x0B97A02F == deviceID) + gDSP_board_type= C6657_EVM; + + return gDSP_board_type; +} + +static inline Uint32 KeyStone_Get_DSP_Number() +{ + TDSP_Board_Type DSP_Board_Type= KeyStone_Get_dsp_board_type(); + + if(DUAL_NYQUIST_EVM==DSP_Board_Type) + { + /*Nyquist EVM use boot configure pin 4 and 5 to identify DSPs*/ + return (( gpBootCfgRegs->BOOT_REG0 >> (3+1) ) & 0x03); + } + + /*if use DNUM to differentiate DSPs for two DSPs test, + the program must be run on core 0 of DSP 0 and core 1 of DSP1*/ + return DNUM; +} + +/*clear all interrupt flag/status, setup ISTP to begining of LL2*/ +extern void CPU_interrupt_init(); +/*enable interrupt to CPU: IER |= uiIER_en_mask; GIE=1*/ +extern void CPU_interrupt_enable(Uint32 uiIER_en_mask); + +//get device speed grade from the EFUSE register +extern void KeyStone_get_device_speed_grade(); + +/*Get device information including device type, boot mode, endian information, +speed grade, required voltage...*/ +extern void KeyStone_get_device_info(); + +/*common initialization for internal modules in K2 device. +enable memory protection interrupts, EDC for MSMC RAM*/ +extern void KeyStone_common_device_init(); + +/* enable TSC, EDC for local RAM; clear cache; protect L1 as cache */ +extern void KeyStone_common_CPU_init(); + + +#endif diff --git a/bsp/ti-tms320c6678/readme.txt b/bsp/ti-tms320c6678/readme.txt index 3309207357..84f608122c 100644 --- a/bsp/ti-tms320c6678/readme.txt +++ b/bsp/ti-tms320c6678/readme.txt @@ -1,3 +1,4 @@ - 本工程使用TI公司编译器CCS5.5进行编译,工程中使用到了TI官方提供的K1_STK_v1.1, -如有需要的请到TI官方论坛自行下载,并将K1_STK_v1.1中的KeyStone_common.c和KeyStone_common.h文件 -放置到本工程的driver目录下。 \ No newline at end of file + 本工程使用TI公司编译器CCS5.5进行编译,需要安装TI提供的CSL库pdk_C6678_1_1_2_6, +我的安装路径为C盘。 +"C:\ti\pdk_C6678_1_1_2_6\packages" +"C:\ti\pdk_C6678_1_1_2_6\packages\ti\csl" \ No newline at end of file diff --git a/libcpu/ti-dsp/c6x/context.asm b/libcpu/ti-dsp/c6x/context.asm index 2a57e9414d..aa7a138887 100644 --- a/libcpu/ti-dsp/c6x/context.asm +++ b/libcpu/ti-dsp/c6x/context.asm @@ -18,11 +18,6 @@ ;----------------------------------------------------------- DP .set B14 SP .set B15 - -;----------------------------------------------------------- -; extern variable -;----------------------------------------------------------- - .ref rt_system_stack_top ; ;----------------------------------------------------------- ; @@ -165,8 +160,7 @@ rt_hw_context_switch_to: LDDW .D2T2 *++SP[1],B13:B12 ; get PC (B13) and CSR (B12) NOP 2 MV B8,B0 - [B0] B _rt_thread_interrupt_stack - NOP 5 + [B0] BNOP _rt_thread_interrupt_stack, 5 ; ; this maybe do better ; @@ -275,7 +269,6 @@ rt_interrupt_context_restore: NOP 4 CMPEQ 1,A1,A2 [A2] BNOP rt_preempt_context_restore,5 - NOP 5 LDDW .D2T2 *++SP[1],B9:B8 ; get TSR (B9) LDDW .D2T2 *++SP[1],B11:B10 ; get RILC (B11) and ILC (B10) LDDW .D2T2 *++SP[1],B13:B12 ; get PC (B13) and CSR (B12) diff --git a/libcpu/ti-dsp/c6x/contextinc.asm b/libcpu/ti-dsp/c6x/contextinc.asm index d51211ae9e..3bc6afafc6 100644 --- a/libcpu/ti-dsp/c6x/contextinc.asm +++ b/libcpu/ti-dsp/c6x/contextinc.asm @@ -8,6 +8,11 @@ ; 2021-11-16 Dystopia the first version ; +;----------------------------------------------------------- +; extern variable +;----------------------------------------------------------- + .ref rt_system_stack_top + ;----------------------------------------------------------- ; macro definition ;----------------------------------------------------------- diff --git a/libcpu/ti-dsp/c6x/interrupt.c b/libcpu/ti-dsp/c6x/interrupt.c index 2be2f88313..1f532f6c32 100644 --- a/libcpu/ti-dsp/c6x/interrupt.c +++ b/libcpu/ti-dsp/c6x/interrupt.c @@ -26,7 +26,7 @@ rt_uint32_t rt_thread_switch_interrupt_flag; void rt_hw_interrupt_init(void) { // initial system trap - rt_trap_init(); + //rt_trap_init(); /* init exceptions table */ rt_memset(isr_table, 0x00, sizeof(isr_table)); diff --git a/libcpu/ti-dsp/c6x/intexc.asm b/libcpu/ti-dsp/c6x/intexc.asm index 2490977331..81a77426ec 100644 --- a/libcpu/ti-dsp/c6x/intexc.asm +++ b/libcpu/ti-dsp/c6x/intexc.asm @@ -65,14 +65,6 @@ SP .set B15 ;----------------------------------------------------------- ; -;----------------------------------------------------------- -; extern variable -;----------------------------------------------------------- - .ref rt_system_stack_top -; -;----------------------------------------------------------- -; - ;----------------------------------------------------------- ; interrupt macro definition ;----------------------------------------------------------- diff --git a/libcpu/ti-dsp/c6x/stack.c b/libcpu/ti-dsp/c6x/stack.c index 3fe3377a1c..05e9534538 100644 --- a/libcpu/ti-dsp/c6x/stack.c +++ b/libcpu/ti-dsp/c6x/stack.c @@ -31,8 +31,8 @@ extern rt_uint32_t rt_hw_get_current_dp(void); rt_uint8_t *rt_hw_stack_init(void *tentry, void *parameter, rt_uint8_t *stack_addr, void *texit) { - rt_hw_thread_stack_register *thread_context; - rt_uint32_t stk; + rt_hw_thread_stack_register *thread_context = RT_NULL; + rt_uint32_t stk = 0; stack_addr += sizeof(rt_uint32_t); stack_addr = (rt_uint8_t *)RT_ALIGN_DOWN((rt_uint32_t)stack_addr, 8); diff --git a/libcpu/ti-dsp/c6x/trap.h b/libcpu/ti-dsp/c6x/trap.h index 12734df4a7..d895344728 100644 --- a/libcpu/ti-dsp/c6x/trap.h +++ b/libcpu/ti-dsp/c6x/trap.h @@ -90,8 +90,9 @@ extern int __ffs(int val); static inline int fls(int x) { if (!x) + { return 0; - + } return 32 - __fls(x); } @@ -107,8 +108,9 @@ static inline int fls(int x) static inline int ffs(int x) { if (!x) + { return 0; - + } return __ffs(x) + 1; } From 466f9ad4e32873008eb6bbd97b4d2ac65e87c7ee Mon Sep 17 00:00:00 2001 From: Huang bo Date: Wed, 15 Dec 2021 10:43:06 +0800 Subject: [PATCH 14/24] =?UTF-8?q?=E5=88=A0=E9=99=A4=E4=BE=9D=E8=B5=96TI?= =?UTF-8?q?=E7=9A=84KeyStone=5Fcommon.c=E6=96=87=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- bsp/ti-tms320c6678/applications/board.c | 4 +- bsp/ti-tms320c6678/common/KeyStone_common.c | 4355 ------------------- bsp/ti-tms320c6678/common/KeyStone_common.h | 1090 ----- bsp/ti-tms320c6678/common/common.c | 201 + bsp/ti-tms320c6678/common/common.h | 110 + bsp/ti-tms320c6678/driver/drv_timer.c | 9 +- bsp/ti-tms320c6678/driver/drv_timer.h | 3 + libcpu/ti-dsp/c6x/c66xx.h | 28 +- libcpu/ti-dsp/c6x/interrupt.c | 5 + 9 files changed, 345 insertions(+), 5460 deletions(-) delete mode 100644 bsp/ti-tms320c6678/common/KeyStone_common.c delete mode 100644 bsp/ti-tms320c6678/common/KeyStone_common.h create mode 100644 bsp/ti-tms320c6678/common/common.c create mode 100644 bsp/ti-tms320c6678/common/common.h diff --git a/bsp/ti-tms320c6678/applications/board.c b/bsp/ti-tms320c6678/applications/board.c index 51a21f6cd8..0e622765da 100644 --- a/bsp/ti-tms320c6678/applications/board.c +++ b/bsp/ti-tms320c6678/applications/board.c @@ -11,7 +11,7 @@ #include "board.h" #include "interrupt.h" #include "drv_timer.h" -#include "KeyStone_common.h" +#include "common.h" #include @@ -21,7 +21,7 @@ void rt_hw_board_init(void) { // initial CPU core - KeyStone_common_CPU_init(); + keystone_cpu_init(); // initial interrupt controller rt_hw_interrupt_init(); diff --git a/bsp/ti-tms320c6678/common/KeyStone_common.c b/bsp/ti-tms320c6678/common/KeyStone_common.c deleted file mode 100644 index bfa6fbac3c..0000000000 --- a/bsp/ti-tms320c6678/common/KeyStone_common.c +++ /dev/null @@ -1,4355 +0,0 @@ -/****************************************************************************** - - Copyright (C), 2001-2012, Texas Instrument. - - ****************************************************************************** - File Name : KeyStone_common.c - Version : Initial Draft - Author : Brighton Feng - Created : 2010-12-12 - Last Modified : - Description : KeyStone common miscellaneous functions and definitions - History : - 1.Date : 2010-12-12 - Author : Brighton Feng - Modification: Created file - - 2.Date : 2012-10-6 - Author : Brighton Feng - Modification : Add memory protection and EDC configuration - - 3.Date : 2014-12-8 - Author : Brighton Feng - Modification : Add common device, CPU, interrupt initialization functions. - Print device information including device type, speed grade, - boot mode, required voltage, ID�� - Add EDMA enable/disable functions. - To support square wave generation by timer. -******************************************************************************/ - -#include -#include -#include -#include -#include -#include -#include -#include -#include "CSL_msmc.h" -#include "CSL_msmcAux.h" -#include "KeyStone_common.h" - -/*----------------------------------------------* - * external variables * - *----------------------------------------------*/ - -/*----------------------------------------------* - * external routine prototypes * - *----------------------------------------------*/ - -/*----------------------------------------------* - * internal routine prototypes * - *----------------------------------------------*/ - -/*----------------------------------------------* - * project-wide global variables * - *----------------------------------------------*/ -CSL_XmcRegs * gpXMC_regs = (CSL_XmcRegs *) CSL_XMC_CONFIG_REGS; -CSL_CgemRegs * gpCGEM_regs = (CSL_CgemRegs *)CSL_CGEM0_5_REG_BASE_ADDRESS_REGS; -CSL_BootcfgRegs * gpBootCfgRegs = (CSL_BootcfgRegs *)CSL_BOOT_CFG_REGS; -CSL_PllcRegs * gpPLLC_regs = (CSL_PllcRegs * )CSL_PLL_CONTROLLER_REGS; -CSL_PscRegs * gpPSC_regs = (CSL_PscRegs *)CSL_PSC_REGS; -CSL_MsmcRegs * gpMSMC_regs = (CSL_MsmcRegs *)CSL_MSMC_CONFIG_REGS; -CSL_GpioRegs * gpGPIO_regs= (CSL_GpioRegs * )CSL_GPIO_REGS; - -CSL_CPINTCRegs* gpCIC0_regs = (CSL_CPINTCRegs*)CSL_CP_INTC_0_REGS; -CSL_CPINTCRegs* gpCIC1_regs = (CSL_CPINTCRegs*)CSL_CP_INTC_1_REGS; -/*The register pointer for the CIC routing events DSP core. -By default, it is CIC0; but for core 4~7 of C6678, it is CIC1*/ -CSL_CPINTCRegs* gpCIC_regs= (CSL_CPINTCRegs*)CSL_CP_INTC_0_REGS; - -CSL_TpccRegs* gpEDMA_CC0_regs = (CSL_TpccRegs*)CSL_EDMA0CC_REGS; -CSL_TpccRegs* gpEDMA_CC1_regs = (CSL_TpccRegs*)CSL_EDMA1CC_REGS; -CSL_TpccRegs* gpEDMA_CC2_regs = (CSL_TpccRegs*)CSL_EDMA2CC_REGS; -CSL_TpccRegs* gpEDMA_CC_regs[3] = { - (CSL_TpccRegs*)CSL_EDMA0CC_REGS, - (CSL_TpccRegs*)CSL_EDMA1CC_REGS, - (CSL_TpccRegs*)CSL_EDMA2CC_REGS -}; - -CSL_TptcRegs * gpEDMA_TC_0_0_regs=(CSL_TptcRegs *) CSL_EDMA0TC0_REGS; -CSL_TptcRegs * gpEDMA_TC_0_1_regs=(CSL_TptcRegs *) CSL_EDMA0TC1_REGS; -CSL_TptcRegs * gpEDMA_TC_1_0_regs=(CSL_TptcRegs *) CSL_EDMA1TC0_REGS; -CSL_TptcRegs * gpEDMA_TC_1_1_regs=(CSL_TptcRegs *) CSL_EDMA1TC1_REGS; -CSL_TptcRegs * gpEDMA_TC_1_2_regs=(CSL_TptcRegs *) CSL_EDMA1TC2_REGS; -CSL_TptcRegs * gpEDMA_TC_1_3_regs=(CSL_TptcRegs *) CSL_EDMA1TC3_REGS; -CSL_TptcRegs * gpEDMA_TC_2_0_regs=(CSL_TptcRegs *) CSL_EDMA2TC0_REGS; -CSL_TptcRegs * gpEDMA_TC_2_1_regs=(CSL_TptcRegs *) CSL_EDMA2TC1_REGS; -CSL_TptcRegs * gpEDMA_TC_2_2_regs=(CSL_TptcRegs *) CSL_EDMA2TC2_REGS; -CSL_TptcRegs * gpEDMA_TC_2_3_regs=(CSL_TptcRegs *) CSL_EDMA2TC3_REGS; - -CSL_TptcRegs * gpEDMA_TC_regs[10]= { - (CSL_TptcRegs *) CSL_EDMA0TC0_REGS, - (CSL_TptcRegs *) CSL_EDMA0TC1_REGS, - (CSL_TptcRegs *) CSL_EDMA1TC0_REGS, - (CSL_TptcRegs *) CSL_EDMA1TC1_REGS, - (CSL_TptcRegs *) CSL_EDMA1TC2_REGS, - (CSL_TptcRegs *) CSL_EDMA1TC3_REGS, - (CSL_TptcRegs *) CSL_EDMA2TC0_REGS, - (CSL_TptcRegs *) CSL_EDMA2TC1_REGS, - (CSL_TptcRegs *) CSL_EDMA2TC2_REGS, - (CSL_TptcRegs *) CSL_EDMA2TC3_REGS -}; - -CSL_TmrPlusRegs * gpTimer0Regs = (CSL_TmrPlusRegs *)CSL_TIMER_0_REGS; -CSL_TmrPlusRegs * gpTimer1Regs = (CSL_TmrPlusRegs *)CSL_TIMER_1_REGS; -CSL_TmrPlusRegs * gpTimer2Regs = (CSL_TmrPlusRegs *)CSL_TIMER_2_REGS; -CSL_TmrPlusRegs * gpTimer3Regs = (CSL_TmrPlusRegs *)CSL_TIMER_3_REGS; -CSL_TmrPlusRegs * gpTimer4Regs = (CSL_TmrPlusRegs *)CSL_TIMER_4_REGS; -CSL_TmrPlusRegs * gpTimer5Regs = (CSL_TmrPlusRegs *)CSL_TIMER_5_REGS; -CSL_TmrPlusRegs * gpTimer6Regs = (CSL_TmrPlusRegs *)CSL_TIMER_6_REGS; -CSL_TmrPlusRegs * gpTimer7Regs = (CSL_TmrPlusRegs *)CSL_TIMER_7_REGS; -CSL_TmrPlusRegs * gpTimer8Regs = (CSL_TmrPlusRegs *)(CSL_TIMER_7_REGS+(CSL_TIMER_7_REGS-CSL_TIMER_6_REGS)); -CSL_TmrPlusRegs * gpTimerRegs[9] = { - (CSL_TmrPlusRegs *)CSL_TIMER_0_REGS, - (CSL_TmrPlusRegs *)CSL_TIMER_1_REGS, - (CSL_TmrPlusRegs *)CSL_TIMER_2_REGS, - (CSL_TmrPlusRegs *)CSL_TIMER_3_REGS, - (CSL_TmrPlusRegs *)CSL_TIMER_4_REGS, - (CSL_TmrPlusRegs *)CSL_TIMER_5_REGS, - (CSL_TmrPlusRegs *)CSL_TIMER_6_REGS, - (CSL_TmrPlusRegs *)CSL_TIMER_7_REGS, - (CSL_TmrPlusRegs *)(CSL_TIMER_7_REGS+(CSL_TIMER_7_REGS-CSL_TIMER_6_REGS)) -}; - -/*MPU for peripherals registers and data space*/ -CSL_MpuRegs * gpMPU0_regs= (CSL_MpuRegs *)CSL_MPU_0_REGS; -CSL_MpuRegs * gpMPU1_regs= (CSL_MpuRegs *)CSL_MPU_1_REGS; -CSL_MpuRegs * gpMPU2_regs= (CSL_MpuRegs *)CSL_MPU_2_REGS; -CSL_MpuRegs * gpMPU3_regs= (CSL_MpuRegs *)CSL_MPU_3_REGS; - -CSL_Emif4fRegs * gpDDR_regs= (CSL_Emif4fRegs *)CSL_DDR3_EMIF_CONFIG_REGS; -unsigned int gDSP_Core_Speed_Hz= 1000000000; //DSP core clock speed in Hz -TDSP_Board_Type gDSP_board_type= UNKNOWN; - -/*----------------------------------------------* - * module-wide global variables * - *----------------------------------------------*/ - -/*----------------------------------------------* - * constants * - *----------------------------------------------*/ - -/*----------------------------------------------* - * macros * - *----------------------------------------------*/ - -/*----------------------------------------------* - * routines' implementations * - *----------------------------------------------*/ - -/***************************************************************************** - Prototype : KeyStone_main_PLL_init - Description : DSP core PLL configuration - DSP core will be configured to run at ref_clock_MHz*multiplier/divisor - Input : float ref_clock_MHz - unsigned int multiplier: 1~4096 - unsigned int divisor: 1~64 - Output : - Return Value : - - History : - 1.Date : 2010-12-12 - Author : Brighton Feng - Modification : Created function - 2.Date : May 19, 2013 - Author : Brighton Feng - Modification : update parameter check; replace constant with macro - -*****************************************************************************/ -void KeyStone_main_PLL_init (float ref_clock_MHz, - unsigned int multiplier, unsigned int divisor) -{ - unsigned int i; - - if(0==divisor) - { - puts("Error: PLL input divider = 0"); - return; - } - - if(64SECCTL & PLLCTL_BYPASS_MASK) - { - /*a. In MAINPLLCTL1, write ENSAT = 1 (for optimal PLL operation) */ - gpBootCfgRegs->CORE_PLL_CTL1 |= PLLCTL1_ENSAT_MASK; /*Set ENSAT bit = 1*/ - - /*b. In PLLCTL, write PLLEN = 0 (bypass enabled in PLL controller mux) */ - gpPLLC_regs->PLLCTL &= ~CSL_PLLC_PLLCTL_PLLEN_MASK; - - /*c. In PLLCTL, write PLLENSRC = 0 (enable PLLEN to control PLL controller mux */ - gpPLLC_regs->PLLCTL &= ~CSL_PLLC_PLLCTL_PLLENSRC_MASK; - - /*d. Wait 4 cycles of the reference clock CLKIN (to make sure the PLL controller */ - /*mux switches properly to the bypass) */ - for(i=0; i< 4; i++) - asm(" nop 5"); - - /*e. In SECCTL, write BYPASS = 1 (bypass enabled in PLL mux) */ - gpPLLC_regs->SECCTL |= PLLCTL_BYPASS_MASK; - - /*f. In PLLCTL, write PLLPWRDN = 1 (power down the PLL) */ - gpPLLC_regs->PLLCTL |= CSL_PLLC_PLLCTL_PLLPWRDN_MASK; //Power down the PLL - - /*g. Wait for at least 5 ��s based on the reference clock CLKIN (PLL power down */ - /*toggling time) */ - for(i=0; i< 1000; i++) - asm(" nop 5"); - - /*h. In PLLCTL, write PLLPWRDN = 0 (power up the PLL) */ - gpPLLC_regs->PLLCTL &= ~CSL_PLLC_PLLCTL_PLLPWRDN_MASK; // Power up PLL - } - else - { - /*a. In PLLCTL, write PLLEN = 0 (bypass enabled in PLL controller mux) */ - gpPLLC_regs->PLLCTL &= (~CSL_PLLC_PLLCTL_PLLEN_MASK); - - /*b. In PLLCTL, write PLLENSRC = 0 (enable PLLEN to control PLL controller mux */ - gpPLLC_regs->PLLCTL &= (~CSL_PLLC_PLLCTL_PLLENSRC_MASK); - - /*c. Wait 4 cycles of the reference clock CLKIN (to make sure the PLL controller */ - /*mux switches properly to the bypass) */ - for(i=0; i< 4*multiplier/divisor; i++) - asm(" nop 5"); - } - - /*4. PLLM is split in two different registers. Program PLLM[5:0] in PLL multiplier */ - /*control register (PLLM) and PLLM[12:6] in MAINPLLCTL0 register */ - /*5. BWADJ is split in two different registers. Program BWADJ[7:0] in */ - /*MAINPLLCTL0 and BWADJ[11:8] in MAINPLLCTL1 register. BWADJ value */ - /*must be set to ((PLLM + 1) >> 1) - 1) */ - /*6. Program PLLD in MAINPLLCTL0 register */ - gpBootCfgRegs->CORE_PLL_CTL0 = ((multiplier-1)<PLLM= (multiplier*2-1)&0x3F; - gpBootCfgRegs->CORE_PLL_CTL1 &= ~PLLCTL1_BWADJ_MASK; - gpBootCfgRegs->CORE_PLL_CTL1 |= (multiplier-1)>>8; /*BWADJ[11:8]*/ - - /*7. In SECCTL, write OD (Output Divide) = 1 (that is divide-by-2) */ - gpPLLC_regs->SECCTL &= ~PLLCTL_OD_MASK; - gpPLLC_regs->SECCTL |= 1<PLLSTAT) & CSL_PLLC_PLLSTAT_GOSTAT_MASK); - - /* Step 8b: Program the RATIO field in PLLDIVn to the desired new divide-down rate. - If RATIO field is changed, the PLL controller will flag the change in the - corresponding bit of DCHANGE*/ - gpPLLC_regs->PLLDIV1_3[3-1] = (3-1) | CSL_PLLC_PLLDIV1_3_DNEN_MASK; //Set PLLDIV3 - gpPLLC_regs->PLLDIV4_16[4-4] = (5-1) | CSL_PLLC_PLLDIV4_16_DNEN_MASK; //Set PLLDIV4 - gpPLLC_regs->PLLDIV4_16[7-4] = (6-1) | CSL_PLLC_PLLDIV4_16_DNEN_MASK; //Set PLLDIV7 - - /* Step 8c: Set GOSET bit in PLLCMD to initiate the GO operation to change the divide - values and align the SYSCLKs as programmed */ - gpPLLC_regs->PLLCMD |= CSL_PLLC_PLLCMD_GOSET_MASK; - - /*Step 8d/e: Read the GOSTAT bit in PLLSTAT to make sure the bit returns to 0 to - indicate that the GO operation has completed */ - while((gpPLLC_regs->PLLSTAT) & CSL_PLLC_PLLSTAT_GOSTAT_MASK); -#endif - - /*9. In PLLCTL , write PLLRST = 1 (PLL reset is asserted)*/ - gpPLLC_regs->PLLCTL |= CSL_PLLC_PLLCTL_PLLRST_MASK; - - /*10. Wait for at least 7 ��s based on the reference clock CLKIN (PLL reset time) */ - for(i=0; i< 2000; i++) - asm(" nop 5"); - - /*11. In PLLCTL, write PLLRST = 0 (PLL reset is released) */ - gpPLLC_regs->PLLCTL &= ~CSL_PLLC_PLLCTL_PLLRST_MASK; - - /*12. Wait for at least 2000 �� CLKIN cycles �� (PLLD + 1) (PLL lock time) */ - for(i=0; i< 400*multiplier; i++) - asm(" nop 5"); - - /*13. In SECCTL, write BYPASS = 0 (enable PLL mux to switch to PLL mode) */ - gpPLLC_regs->SECCTL &= ~PLLCTL_BYPASS_MASK; - - /*14. Set the PLLEN bit in PLLCTL to 1 to enable PLL mode*/ - gpPLLC_regs->PLLCTL |= CSL_PLLC_PLLCTL_PLLEN_MASK; - -} -/***************************************************************************** - Prototype : KeyStone_PLL_init - Description : Config the PLL of PA and DDR - target clock speed will be ref_clock_MHz/inputDivisor*multiplier/outputDivisor - Input : unsigned int inputDivisor - unsigned int multiplier - unsigned int outputDivisor - Output : None - Return Value : 0 for success, other value for error - - History : - 1.Date : May 18, 2013 - Author : Brighton Feng - Modification : Created function - -*****************************************************************************/ -int KeyStone_PLL_init (PLL_ControlRegs * PLL_Regs, unsigned int inputDivisor, - unsigned int multiplier, unsigned int outputDivisor) -{ - if(0==inputDivisor) - { - puts("Error: PLL input divider = 0"); - return 1; - } - - if(64PLL_CTL1 = PLLCTL1_ENSAT_MASK; - - /*2. In PLLCTL0, write BYPASS = 1 (set the PLL in Bypass)*/ - PLL_Regs->PLL_CTL0 |= PLLCTL_BYPASS_MASK; - - /*3. Program PLLM and PLLD in PLLCTL0 register*/ - /*4. Program BWADJ[7:0] in PLLCTL0 and BWADJ[11:8] in PLLCTL1 register. - BWADJ value must be set to ((PLLM + 1) >> 1) �C 1)*/ - PLL_Regs->PLL_CTL0 = ((multiplier/2-1)<PLL_CTL1 &= ~PLLCTL1_BWADJ_MASK; - PLL_Regs->PLL_CTL1 |= (multiplier/2-1)>>8; /*BWADJ[11:8]*/ - - /*5. In PLLCTL1, write PLLRST = 1 (PLL is reset)*/ - PLL_Regs->PLL_CTL1 |= PLLCTL1_PLLRESET_MASK; //Set RESET bit = 1 - - /*6. Wait for at least 7 us based on the reference clock (PLL reset time)*/ - TSC_delay_us(7); - - /*For PASS, In PASSPLLCTL1, write PLLSELECT = 1 - (for selecting the output of PA PLL as the input to PASS)*/ - if(PLL_Regs==(PLL_ControlRegs *)gpBootCfgRegs->PA_PLL_CTL0) - PLL_Regs->PLL_CTL1 |= PLLCTL1_PAPLL_MASK; - - /*7. In PLLCTL1, write PLLRST = 0 (PLL reset is released)*/ - PLL_Regs->PLL_CTL1 &= ~PLLCTL1_PLLRESET_MASK; //Clear RESET bit - - /*8. Wait for at least 500 * REFCLK cycles * (PLLD + 1) (PLL lock time)*/ - TSC_delay_us(500); - - /*9. In PLLCTL0, write BYPASS = 0 (switch to PLL mode)*/ - PLL_Regs->PLL_CTL0 &= ~PLLCTL_BYPASS_MASK ; - - return 0; -} -/***************************************************************************** - Prototype : KeyStone_PASS_PLL_init - Description : Config the PASS PLL - target clock speed will be ref_clock_MHz/divisor*multiplier - Input : float ref_clock_MHz - unsigned int multiplier: 1~4096 - unsigned int divisor: 1~64 - Output : None - Return Value : - - History : - 1.Date : 2013-2-14 - Author : Brighton Feng - Modification : Created function - -*****************************************************************************/ -void KeyStone_PASS_PLL_init (float ref_clock_MHz, - unsigned int multiplier, unsigned int divisor) -{ - //output divisor for PASS PLL should be 2 - if(0==KeyStone_PLL_init((PLL_ControlRegs *)&gpBootCfgRegs->PA_PLL_CTL0, - divisor, multiplier*2, 2)) - { - printf("Initialize PASS PLL clock = %.2fMHz/%dx%d = %.3fMHz\n", - ref_clock_MHz, divisor, multiplier, - ref_clock_MHz*multiplier/divisor); - } -} - -/***************************************************************************** - Prototype : KeyStone_DDR_PLL_init - Description : Config the DDR PLL - target clock speed will be ref_clock_MHz/divisor*multiplier - Input : float ref_clock_MHz - unsigned int multiplier: 1~4096 - unsigned int divisor: 1~64 - Output : None - Return Value : - - History : - 1.Date : 2013-8-18 - Author : Brighton Feng - Modification : Created function - -*****************************************************************************/ -void KeyStone_DDR_PLL_init (float ref_clock_MHz, - unsigned int multiplier, unsigned int divisor) -{ - //output divisor for DDR PLL should be 2 - if(0==KeyStone_PLL_init((PLL_ControlRegs *)&gpBootCfgRegs->DDR3_PLL_CTL0, - divisor, multiplier, 2)) - { - printf("Initialize DDR speed = %.2fMHzx/%dx%d = %.3fMTS\n", - ref_clock_MHz, divisor, multiplier, - ref_clock_MHz*multiplier/divisor); - } -} - -/*===============================TSC===================================*/ -unsigned int cycle_measure_overhead=50; -/***************************************************************************** - Prototype : calc_cycle_measure_overhead - Description : calclucate the cycles measurement overhead - Input : None - Output : None - Return Value : - - History : - 1.Date : 2010/12/12 - Author : Brighton Feng - Modification : Created function - -*****************************************************************************/ -void calc_cycle_measure_overhead() -{ - unsigned int cycle_cold, cycle_warm; - cycle_cold= TSCL; - cycle_cold = TSC_getDelay(cycle_cold); - cycle_warm= TSCL; - cycle_warm = TSC_getDelay(cycle_warm); - cycle_measure_overhead = (cycle_cold + cycle_warm)/2; -} - -/***************************************************************************** - Prototype : TSC_init - Description : Initialize Time stamp counter to measure cycles - Input : None - Output : None - Return Value : - - History : - 1.Date : 2010/12/12 - Author : Brighton Feng - Modification : Created function - -*****************************************************************************/ -void TSC_init() -{ - TSCL = 0; /* Enable the TSC */ - calc_cycle_measure_overhead(); -} - -/***************************************************************************** - Prototype : TSC_delay_ms - Description : Implement the delay function in millisecond - Input : Uint32 ms - Output : None - Return Value : - - History : - 1.Date : 2010/12/12 - Author : Brighton Feng - Modification : Created function - -*****************************************************************************/ -void TSC_delay_ms(Uint32 ms) -{ - volatile unsigned long long startTSC, currentTSC; - unsigned long long delay_cycles; - Uint32 tscl, tsch; - - tscl= TSCL; - tsch= TSCH; - startTSC= _itoll(tsch,tscl); - - delay_cycles= ((unsigned long long)ms*gDSP_Core_Speed_Hz/1000); - - do - { - tscl= TSCL; - tsch= TSCH; - currentTSC= _itoll(tsch,tscl); - } - while((currentTSC-startTSC)TGCR) - { - gpTimerRegs[timer_num]->TGCR= 0; - gpTimerRegs[timer_num]->TCR= 0; - } -} - - /***************************************************************************** - Prototype : Timer64_Init - Description : Initialize a 64-bit timer - Input : Timer64_Config * tmrCfg - Output : None - Return Value : - - History : - 1.Date : 2010/12/12 - Author : Brighton Feng - Modification : Created function - -*****************************************************************************/ -void Timer64_Init(Timer64_Config * tmrCfg) -{ - Reset_Timer(tmrCfg->timer_num); - - gpTimerRegs[tmrCfg->timer_num]->CNTLO= 0; - gpTimerRegs[tmrCfg->timer_num]->CNTHI= 0; - - /*please note, in clock mode, two timer periods generate a clock, - one timer period output high voltage level, the other timer period - output low voltage level, so, the timer period should be half to the - desired output clock period*/ - if(TIMER_PERIODIC_CLOCK==tmrCfg->timerMode) - tmrCfg->period= tmrCfg->period/2; - - /*the value written into period register is the expected value minus one*/ - gpTimerRegs[tmrCfg->timer_num]->PRDLO= _loll(tmrCfg->period-1); - gpTimerRegs[tmrCfg->timer_num]->PRDHI= _hill(tmrCfg->period-1); - if(tmrCfg->reload_period>1) - { - gpTimerRegs[tmrCfg->timer_num]->RELLO= _loll(tmrCfg->reload_period-1); - gpTimerRegs[tmrCfg->timer_num]->RELHI= _hill(tmrCfg->reload_period-1); - } - - if(TIMER_WATCH_DOG==tmrCfg->timerMode) - { - gpTimerRegs[tmrCfg->timer_num]->TGCR= - /*Select watch-dog mode*/ - (CSL_TMR_TIMMODE_WDT<timerMode) - { - gpTimerRegs[tmrCfg->timer_num]->TGCR= TMR_TGCR_PLUSEN_MASK - /*for plus featuers, dual 32-bit unchained timer mode should be used*/ - |(CSL_TMR_TIMMODE_DUAL_UNCHAINED<timer_num]->INTCTL_STAT= TMR_INTCTLSTAT_EN_ALL_CLR_ALL; - } - else - { - gpTimerRegs[tmrCfg->timer_num]->TGCR= - /*Select 64-bit general timer mode*/ - (CSL_TMR_TIMMODE_GPT<timer_num]->EMUMGT_CLKSPD = (gpTimerRegs[tmrCfg->timer_num]->EMUMGT_CLKSPD& - ~(CSL_TMR_EMUMGT_CLKSPD_FREE_MASK|CSL_TMR_EMUMGT_CLKSPD_SOFT_MASK)); - - if(TIMER_WATCH_DOG==tmrCfg->timerMode) - { - /*enable watchdog timer*/ - gpTimerRegs[tmrCfg->timer_num]->WDTCR = CSL_TMR_WDTCR_WDEN_MASK - |(CSL_TMR_WDTCR_WDKEY_CMD1<timer_num]->TCR= - (CSL_TMR_CLOCK_INP_NOGATE<pulseWidth<timer_num]->WDTCR = CSL_TMR_WDTCR_WDEN_MASK - |(CSL_TMR_WDTCR_WDKEY_CMD2<timerMode) - { - gpTimerRegs[tmrCfg->timer_num]->TCR= - (CSL_TMR_CLOCK_INP_NOGATE<pulseWidth<timerMode) - { - gpTimerRegs[tmrCfg->timer_num]->TCR= - (CSL_TMR_CLOCK_INP_NOGATE<pulseWidth<timerMode) - { - gpTimerRegs[tmrCfg->timer_num]->TCR= - (CSL_TMR_CLOCK_INP_NOGATE<pulseWidth<timer_num]->TCR= - (CSL_TMR_CLOCK_INP_NOGATE<pulseWidth<WDTCR = - (CSL_TMR_WDTCR_WDKEY_CMD1<WDTCR = - (CSL_TMR_WDTCR_WDKEY_CMD2<0x3FFFFFFF) - { - printf("Enable power domain %d timeout!\n", pwrDmnNum); - return -2; - } - } - } - - /* Enable the clocks too*/ - CSL_PSC_setModuleNextState (moduleNum, PSC_MODSTATE_ENABLE); - - /* Start the state transition */ - CSL_PSC_startStateTransition (pwrDmnNum); - - /* Wait until the state transition process is completed. */ - while (!CSL_PSC_isStateTransitionDone (pwrDmnNum)) - { - if(TSC_count_cycle_from(uiStartTSC)>0x3FFFFFFF) - { - printf("Enable clock domain %d timeout!\n", moduleNum); - return -2; - } - } - - /* Return PSC status */ - if ((CSL_PSC_getPowerDomainState(pwrDmnNum) == PSC_PDSTATE_ON) && - (CSL_PSC_getModuleState (moduleNum) == PSC_MODSTATE_ENABLE)) - { - /*Ready for use */ - return 0; - } - else - { - /*Return error */ - return -1; - } -} -/***************************************************************************** - Prototype : KeyStone_disable_PSC_module - Description : Disable the PSC module in KeyStone device - Input : Uint32 pwrDmnNum - Uint32 moduleNum - Output : None - Return Value : - - History : - 1.Date : 2010/2/12 - Author : Brighton Feng - Modification : Created function - -*****************************************************************************/ -Int32 KeyStone_disable_PSC_module (Uint32 pwrDmnNum, Uint32 moduleNum) -{ - Uint32 uiStartTSC= TSCL; - - /* disable the clocks*/ - CSL_PSC_setModuleNextState (moduleNum, PSC_MODSTATE_SWRSTDISABLE); - - /* Start the state transition */ - CSL_PSC_startStateTransition (pwrDmnNum); - - /* Wait until the state transition process is completed. */ - while (!CSL_PSC_isStateTransitionDone (pwrDmnNum)) - { - if(TSC_count_cycle_from(uiStartTSC)>0x3FFFFFFF) - { - printf("Disable clock domain %d timeout!\n", moduleNum); - return -2; - } - } - - /* Return PSC status */ - if (CSL_PSC_getModuleState (moduleNum) == PSC_MODSTATE_SWRSTDISABLE) - { - /*Ready for use */ - return 0; - } - else - { - /*Return error */ - return -1; - } - -} -/***************************************************************************** - Prototype : KeyStone_disable_PSC_Power_Domain - Description : Disable the PSC power domain - Input : Uint32 pwrDmnNum - Output : None - Return Value : - - History : - 1.Date : 2010/12/12 - Author : Brighton Feng - Modification : Created function - -*****************************************************************************/ -Int32 KeyStone_disable_PSC_Power_Domain (Uint32 pwrDmnNum) -{ - Uint32 uiStartTSC= TSCL; - - /* Set Power domain to OFF */ - CSL_PSC_disablePowerDomain (pwrDmnNum); - - /* Start the state transition */ - CSL_PSC_startStateTransition (pwrDmnNum); - - /* Wait until the state transition process is completed. */ - while (!CSL_PSC_isStateTransitionDone (pwrDmnNum)) - { - if(TSC_count_cycle_from(uiStartTSC)>0x3FFFFFFF) - { - printf("Disable power domain %d timeout!\n", pwrDmnNum); - return -2; - } - } - - /* Return PSC status */ - if (CSL_PSC_getPowerDomainState(pwrDmnNum) == PSC_PDSTATE_OFF) - { - /*Ready for use */ - return 0; - } - else - { - /*Return error */ - return -1; - } - -} - -/*============================EDMA=====================================*/ - /***************************************************************************** - Prototype : EDMA_channel_TC_cfg - Description : Setup uiChannel of an EDMA to use uiTC - Input : Uint32 uiCC - Uint32 uiChannel - Uint32 uiTC - Output : None - Return Value : - - History : - 1.Date : 2010/12/12 - Author : Brighton Feng - Modification : Created function - -*****************************************************************************/ -void EDMA_channel_TC_cfg (Uint32 uiCC, - Uint32 uiChannel, Uint32 uiTC) -{ - gpEDMA_CC_regs[uiCC]->TPCC_DMAQNUM[uiChannel/8] = - (gpEDMA_CC_regs[uiCC]->TPCC_DMAQNUM[uiChannel/8]&(~(0xF<<((uiChannel&7)*4)))) - |(uiTC<<((uiChannel&7)*4)); -} -/***************************************************************************** - Prototype : EDMA_TC_priority_cfg - Description : Setup uiChannel of an EDMA TC priority - Input : Uint32 uiCC - Uint32 uiPri - Uint32 uiTC - Output : None - Return Value : - - History : - 1.Date : 2010/12/12 - Author : Brighton Feng - Modification : Created function - -*****************************************************************************/ -void EDMA_TC_priority_cfg(Uint32 uiCC, - Uint32 uiPri, Uint32 uiTC) -{ - gpEDMA_CC_regs[uiCC]->TPCC_QUEPRI= - (gpEDMA_CC_regs[uiCC]->TPCC_QUEPRI&(~(0xF<<((uiTC&3)*4)))) - |(uiPri<<((uiTC&3)*4)); -} -/***************************************************************************** - Prototype : EDMA_init - Description : Initialize all EDMA registers and clear the event - Input : None - Output : None - Return Value : - - History : - 1.Date : 2010/12/12 - Author : Brighton Feng - Modification : Created function - -*****************************************************************************/ -void EDMA_init () -{ - int i; - unsigned int * uipPaRAM; - - /*clear PaRAM*/ - uipPaRAM= (unsigned int *)&(gpEDMA_CC0_regs->PARAMSET[0]); - for(i=0; i<8*CSL_EDMA3_TPCC0_NUM_PARAMSETS; i++) - *uipPaRAM++=0; - - uipPaRAM= (unsigned int *)&(gpEDMA_CC1_regs->PARAMSET[0]); - for(i=0; i<8*CSL_EDMA3_TPCC1_NUM_PARAMSETS; i++) - *uipPaRAM++=0; - - uipPaRAM= (unsigned int *)&(gpEDMA_CC2_regs->PARAMSET[0]); - for(i=0; i<8*CSL_EDMA3_TPCC2_NUM_PARAMSETS; i++) - *uipPaRAM++=0; - - /*Assign PaRAM for different channels*/ - for(i=0; iTPCC_DCHMAP[i] = i<< CSL_TPCC_TPCC_DCHMAP0_PAENTRY_SHIFT; - - for(i=0; iTPCC_DCHMAP[i] = i<< CSL_TPCC_TPCC_DCHMAP0_PAENTRY_SHIFT; - - for(i=0; iTPCC_DCHMAP[i] = i<< CSL_TPCC_TPCC_DCHMAP0_PAENTRY_SHIFT; - - /*Assign TC/Queue for different channels*/ - gpEDMA_CC0_regs->TPCC_DMAQNUM[0]= 0x10101010; - gpEDMA_CC0_regs->TPCC_DMAQNUM[1]= 0x10101010; - - gpEDMA_CC1_regs->TPCC_DMAQNUM[0]= 0x32103210; - gpEDMA_CC1_regs->TPCC_DMAQNUM[1]= 0x32103210; - gpEDMA_CC1_regs->TPCC_DMAQNUM[2]= 0x32103210; - gpEDMA_CC1_regs->TPCC_DMAQNUM[3]= 0x32103210; - gpEDMA_CC1_regs->TPCC_DMAQNUM[4]= 0x32103210; - gpEDMA_CC1_regs->TPCC_DMAQNUM[5]= 0x32103210; - gpEDMA_CC1_regs->TPCC_DMAQNUM[6]= 0x32103210; - gpEDMA_CC1_regs->TPCC_DMAQNUM[7]= 0x32103210; - - gpEDMA_CC2_regs->TPCC_DMAQNUM[0]= 0x32103210; - gpEDMA_CC2_regs->TPCC_DMAQNUM[1]= 0x32103210; - gpEDMA_CC2_regs->TPCC_DMAQNUM[2]= 0x32103210; - gpEDMA_CC2_regs->TPCC_DMAQNUM[3]= 0x32103210; - gpEDMA_CC2_regs->TPCC_DMAQNUM[4]= 0x32103210; - gpEDMA_CC2_regs->TPCC_DMAQNUM[5]= 0x32103210; - gpEDMA_CC2_regs->TPCC_DMAQNUM[6]= 0x32103210; - gpEDMA_CC2_regs->TPCC_DMAQNUM[7]= 0x32103210; - - /*clear any events and status*/ - gpEDMA_CC0_regs->TPCC_ECR= 0xFFFF; - gpEDMA_CC0_regs->TPCC_EECR= 0xFFFF; - gpEDMA_CC0_regs->TPCC_ICR= 0xFFFF; - gpEDMA_CC0_regs->TPCC_IECR= 0xFFFF; - gpEDMA_CC0_regs->TPCC_EMCR= 0xFFFF; - gpEDMA_CC0_regs->TPCC_QEMCR= 0xFFFF; - gpEDMA_CC0_regs->TPCC_CCERRCLR= 0xFFFF; - gpEDMA_CC0_regs->TPCC_SECR= 0xFFFF; - - gpEDMA_CC1_regs->TPCC_ECR= 0xFFFFFFFF; - gpEDMA_CC1_regs->TPCC_ECRH= 0xFFFFFFFF; - gpEDMA_CC1_regs->TPCC_EECR= 0xFFFFFFFF; - gpEDMA_CC1_regs->TPCC_EECRH= 0xFFFFFFFF; - gpEDMA_CC1_regs->TPCC_ICR= 0xFFFFFFFF; - gpEDMA_CC1_regs->TPCC_ICRH= 0xFFFFFFFF; - gpEDMA_CC1_regs->TPCC_IECR= 0xFFFFFFFF; - gpEDMA_CC1_regs->TPCC_IECRH= 0xFFFFFFFF; - gpEDMA_CC1_regs->TPCC_EMCR= 0xFFFFFFFF; - gpEDMA_CC1_regs->TPCC_EMCRH= 0xFFFFFFFF; - gpEDMA_CC1_regs->TPCC_QEMCR= 0xFFFFFFFF; - gpEDMA_CC1_regs->TPCC_CCERRCLR= 0xFFFF; - gpEDMA_CC1_regs->TPCC_SECR= 0xFFFFFFFF; - gpEDMA_CC1_regs->TPCC_SECRH= 0xFFFFFFFF; - - gpEDMA_CC2_regs->TPCC_ECR= 0xFFFFFFFF; - gpEDMA_CC2_regs->TPCC_ECRH= 0xFFFFFFFF; - gpEDMA_CC2_regs->TPCC_EECR= 0xFFFFFFFF; - gpEDMA_CC2_regs->TPCC_EECRH= 0xFFFFFFFF; - gpEDMA_CC2_regs->TPCC_ICR= 0xFFFFFFFF; - gpEDMA_CC2_regs->TPCC_ICRH= 0xFFFFFFFF; - gpEDMA_CC2_regs->TPCC_IECR= 0xFFFFFFFF; - gpEDMA_CC2_regs->TPCC_IECRH= 0xFFFFFFFF; - gpEDMA_CC2_regs->TPCC_EMCR= 0xFFFFFFFF; - gpEDMA_CC2_regs->TPCC_EMCRH= 0xFFFFFFFF; - gpEDMA_CC2_regs->TPCC_QEMCR= 0xFFFFFFFF; - gpEDMA_CC2_regs->TPCC_CCERRCLR= 0xFFFF; - gpEDMA_CC2_regs->TPCC_SECR= 0xFFFFFFFF; - gpEDMA_CC2_regs->TPCC_SECRH= 0xFFFFFFFF; - - for(i=0; iTPTC_ERRCLR= 0xF; - - //enable error interrupt - gpEDMA_TC_regs[i]->TPTC_ERREN= - (1<TPCC_EESR= 1<<(uiChannel); - } - else - { - //enable the EDMA channel - gpEDMA_CC_regs[uiCC]->TPCC_EESRH= 1<<(uiChannel-32); - } -} - -void EDMA_event_disable(Uint32 uiCC, Uint32 uiChannel) -{ - if(uiChannel<32) - { - //disable the EDMA channel - gpEDMA_CC_regs[uiCC]->TPCC_EECR= 1<<(uiChannel); - } - else - { - //disable the EDMA channel - gpEDMA_CC_regs[uiCC]->TPCC_EECRH= 1<<(uiChannel-32); - } -} - -void EDMA_interrupt_enable(Uint32 uiCC, Uint32 uiIntNum) -{ - if(uiIntNum<32) - { - //enable the EDMA channel interrupt - gpEDMA_CC_regs[uiCC]->TPCC_IESR= 1<<(uiIntNum); - } - else - { - //enable the EDMA channel interrupt - gpEDMA_CC_regs[uiCC]->TPCC_IESRH= 1<<(uiIntNum-32); - } -} - -void EDMA_interrupt_disable(Uint32 uiCC, Uint32 uiIntNum) -{ - if(uiIntNum<32) - { - //disable the EDMA channel interrupt - gpEDMA_CC_regs[uiCC]->TPCC_IECR= 1<<(uiIntNum); - } - else - { - //disable the EDMA channel interrupt - gpEDMA_CC_regs[uiCC]->TPCC_IECRH= 1<<(uiIntNum-32); - } -} - -/***************************************************************************** - Prototype : EDMA_wait - Description : wait the pending EDMA complete - Input : EDMA_CC_Channel_Num CC_channel - Output : None - Return Value : - - History : - 1.Date : 2012/10/30 - Author : Brighton Feng - Modification : Created function - -*****************************************************************************/ -void EDMA_wait(EDMA_CC_Channel_Num CC_channel) -{ - CSL_TpccRegs* EDMACCRegs; - unsigned int uiChannel; - volatile Uint32 * TPCC_IPR; - volatile Uint32 * TPCC_ICR; - - EDMACCRegs= gpEDMA_CC_regs[CC_channel>>16]; - uiChannel = CC_channel&0xFF; - - if(uiChannel<32) - { - TPCC_IPR= &EDMACCRegs->TPCC_IPR; - TPCC_ICR= &EDMACCRegs->TPCC_ICR; - } - else - { - TPCC_IPR= &EDMACCRegs->TPCC_IPRH; - TPCC_ICR= &EDMACCRegs->TPCC_ICRH; - uiChannel -= 32; - } - - /*wait for completion*/ - while(0==((*TPCC_IPR)&(1<<(uiChannel)))); - - /*clear completion flag*/ - (*TPCC_ICR)= 1<<(uiChannel); -} - -/***************************************************************************** - Prototype : EDMA_Copy - Description : EDMA copy function with manual trigger - Input : unsigned int srcAddr - unsigned int dstAddr - unsigned int byteCount, <64KB - EDMA_CC_Channel_Num CC_channel - DMA_Wait wait - Output : None - Return Value : - - History : - 1.Date : 2012/10/30 - Author : Brighton Feng - Modification : Created function - -*****************************************************************************/ -void EDMA_copy(unsigned int srcAddr, unsigned int dstAddr, - unsigned int byteCount, EDMA_CC_Channel_Num CC_channel, DMA_Wait wait) -{ - CSL_TpccRegs* EDMACCRegs; - unsigned int uiChannel; - volatile Uint32 * TPCC_ESR; - volatile Uint32 * TPCC_IPR; - volatile Uint32 * TPCC_ICR; - - EDMACCRegs= gpEDMA_CC_regs[CC_channel>>16]; - uiChannel = CC_channel&0xFF; - - EDMACCRegs->PARAMSET[uiChannel].OPT= - CSL_EDMA3_OPT_MAKE(CSL_EDMA3_ITCCH_DIS, - CSL_EDMA3_TCCH_DIS, - CSL_EDMA3_ITCINT_DIS, - CSL_EDMA3_TCINT_EN, - uiChannel, - CSL_EDMA3_TCC_NORMAL, - CSL_EDMA3_FIFOWIDTH_NONE, - CSL_EDMA3_STATIC_DIS, - CSL_EDMA3_SYNC_A, - CSL_EDMA3_ADDRMODE_INCR, - CSL_EDMA3_ADDRMODE_INCR); - EDMACCRegs->PARAMSET[uiChannel].SRC= GLOBAL_ADDR(srcAddr); - EDMACCRegs->PARAMSET[uiChannel].A_B_CNT=CSL_EDMA3_CNT_MAKE(byteCount&0xFFFF, 1); - EDMACCRegs->PARAMSET[uiChannel].DST= GLOBAL_ADDR(dstAddr); - EDMACCRegs->PARAMSET[uiChannel].SRC_DST_BIDX= 0; - EDMACCRegs->PARAMSET[uiChannel].LINK_BCNTRLD= CSL_EDMA3_LINKBCNTRLD_MAKE(0xFFFF, 1); - EDMACCRegs->PARAMSET[uiChannel].SRC_DST_CIDX= 0; - EDMACCRegs->PARAMSET[uiChannel].CCNT= 1; - - if(uiChannel<32) - { - TPCC_ESR= &EDMACCRegs->TPCC_ESR; - TPCC_IPR= &EDMACCRegs->TPCC_IPR; - TPCC_ICR= &EDMACCRegs->TPCC_ICR; - } - else - { - TPCC_ESR= &EDMACCRegs->TPCC_ESRH; - TPCC_IPR= &EDMACCRegs->TPCC_IPRH; - TPCC_ICR= &EDMACCRegs->TPCC_ICRH; - uiChannel -= 32; - } - - /*Manually trigger the EDMA*/ - (*TPCC_ESR)= 1<<(uiChannel); - - if(wait) - { - /*wait for completion*/ - while(0==((*TPCC_IPR)&(1<<(uiChannel)))); - - /*clear completion flag*/ - (*TPCC_ICR)= 1<<(uiChannel); - } -} - -/***************************************************************************** - Prototype : EDMA_fill - Description : EDMA fill function with manual trigger - Input : unsigned int address, must align to 8 bytes boundary - unsigned long long data - unsigned int byteCount, must be multiple of 8 - EDMA_CC_Channel_Num CC_channel - Output : None - Return Value : - - History : - 1.Date : 2013/8/11 - Author : Brighton Feng - Modification : Created function - -*****************************************************************************/ -void EDMA_fill(unsigned int address, unsigned long long data, - unsigned int byteCount, EDMA_CC_Channel_Num CC_channel) -{ - int i; - CSL_TpccRegs* EDMACCRegs; - unsigned int uiChannel, uiChannelShift, uiBCNT; - volatile Uint32 * TPCC_ESR; - volatile Uint32 * TPCC_IPR; - volatile Uint32 * TPCC_ICR; - unsigned long long tempBuf[128/8]; - Uint32 tempBufSize=128, headerSize, tailSize; - - if(tempBufSize>byteCount) - tempBufSize=byteCount; - - for(i=0; i< tempBufSize/8; i++) - tempBuf[i]= data; - - /*split the transfer into 3 sections at 128 byte boundary*/ - if(address&127) //header address not start on 128 byte boundary - { - headerSize= 128- (address&127); - if(headerSize>byteCount) - headerSize=byteCount; - EDMA_copy((Uint32)tempBuf, address, headerSize, CC_channel, DMA_WAIT); - address+= headerSize; - byteCount-= headerSize; - } - - if(byteCount&&((address+byteCount)&127))//tail address not start on 128 byte boundary - { - tailSize= (address+byteCount)&127; - EDMA_copy((Uint32)tempBuf, address+byteCount-tailSize, tailSize, CC_channel, DMA_WAIT); - byteCount-= tailSize; - } - - EDMACCRegs= gpEDMA_CC_regs[CC_channel>>16]; - uiChannel = CC_channel&0xFF; - if(uiChannel<32) - { - TPCC_ESR= &EDMACCRegs->TPCC_ESR; - TPCC_IPR= &EDMACCRegs->TPCC_IPR; - TPCC_ICR= &EDMACCRegs->TPCC_ICR; - uiChannelShift= uiChannel; - } - else - { - TPCC_ESR= &EDMACCRegs->TPCC_ESRH; - TPCC_IPR= &EDMACCRegs->TPCC_IPRH; - TPCC_ICR= &EDMACCRegs->TPCC_ICRH; - uiChannelShift= uiChannel - 32; - } - - EDMACCRegs->PARAMSET[uiChannel].OPT= - CSL_EDMA3_OPT_MAKE(CSL_EDMA3_ITCCH_DIS, - CSL_EDMA3_TCCH_DIS, - CSL_EDMA3_ITCINT_DIS, - CSL_EDMA3_TCINT_EN, - uiChannel, - CSL_EDMA3_TCC_NORMAL, - CSL_EDMA3_FIFOWIDTH_NONE, - CSL_EDMA3_STATIC_EN, //keep PARAM unchanged - CSL_EDMA3_SYNC_AB, - CSL_EDMA3_ADDRMODE_INCR, - CSL_EDMA3_ADDRMODE_INCR); - EDMACCRegs->PARAMSET[uiChannel].SRC= GLOBAL_ADDR(tempBuf); - EDMACCRegs->PARAMSET[uiChannel].SRC_DST_BIDX= CSL_EDMA3_BIDX_MAKE(0, 128); - EDMACCRegs->PARAMSET[uiChannel].LINK_BCNTRLD= CSL_EDMA3_LINKBCNTRLD_MAKE(0xFFFF, 0); - EDMACCRegs->PARAMSET[uiChannel].SRC_DST_CIDX= 0; - EDMACCRegs->PARAMSET[uiChannel].CCNT= 1; - - while(byteCount) //the reminding must be multiple of 128 bytes - { - uiBCNT= byteCount/128; - if(uiBCNT>65535) - uiBCNT= 65535; - - EDMACCRegs->PARAMSET[uiChannel].A_B_CNT= CSL_EDMA3_CNT_MAKE(128, uiBCNT); - EDMACCRegs->PARAMSET[uiChannel].DST= GLOBAL_ADDR(address); - - /*Manually trigger the EDMA*/ - (*TPCC_ESR)= 1<<(uiChannelShift); - - /*wait for completion*/ - while(0==((*TPCC_IPR)&(1<<(uiChannelShift)))); - - /*clear completion flag*/ - (*TPCC_ICR)= 1<<(uiChannelShift); - - byteCount -= uiBCNT*128; - address += uiBCNT*128; - } -} - -/***************************************************************************** - Prototype : IDMA_wait - Description : wait the pending IDMA complete - Input : None - Output : None - Return Value : - - History : - 1.Date : 2012/10/28 - Author : Brighton Feng - Modification : Created function - -*****************************************************************************/ -void IDMA_wait() -{ - /* Wait until copying is completed */ - while (gpCGEM_regs->IDMA1_STAT); -} -/***************************************************************************** - Prototype : IDMA_copy - Description : implement the data copy via IDMA - Input : unsigned int srcAddr - unsigned int dstAddr - unsigned int byteCount, <64KB - IDMA_Wait wait - Output : None - Return Value : - - History : - 1.Date : 2012/10/28 - Author : Brigthon - Modification : Created function - -*****************************************************************************/ -void IDMA_copy(unsigned int srcAddr, unsigned int dstAddr, - unsigned int byteCount, DMA_Wait wait) -{ - gpCGEM_regs->IDMA1_SOURCE= srcAddr; - gpCGEM_regs->IDMA1_DEST= dstAddr; - gpCGEM_regs->IDMA1_COUNT= byteCount&0xFFFC; - - if(wait) - { - /* Wait until copying is completed */ - while (gpCGEM_regs->IDMA1_STAT); - } -} -/***************************************************************************** - Prototype : EDMA_CC_error_handler - Description : Edma channel controller error processing - Input : Uint32 edmaNum, EDMA module number (0~2) - Output : None - Return Value : - - History : - 1.Date : 2012/11/7 - Author : Brighton Feng - Modification : Created function - -*****************************************************************************/ -void EDMA_CC_error_handler(Uint32 edmaNum) -{ - int i; - CSL_TpccRegs* EDMACCRegs= gpEDMA_CC_regs[edmaNum]; - Uint32 EMR, EMRH= 0, QEMR, CCERR; - - //read error status - EMR= EDMACCRegs->TPCC_EMR; - QEMR= EDMACCRegs->TPCC_QEMR; - CCERR= EDMACCRegs->TPCC_CCERR; - exception_record.status.ext_sts.info.edma.CC_info.EMR= EMR; - exception_record.status.ext_sts.info.edma.CC_info.QEMR= QEMR; - exception_record.status.ext_sts.info.edma.CC_info.CCERR= CCERR; - - //clear error status - EDMACCRegs->TPCC_EMCR= EMR; - EDMACCRegs->TPCC_QEMCR= QEMR; - EDMACCRegs->TPCC_CCERRCLR= CCERR; - - //channel 32~63 for EDMA CC1 and CC2 - if(0TPCC_EMRH; - exception_record.status.ext_sts.info.edma.CC_info.EMRH= EMRH; - - //clear error status - EDMACCRegs->TPCC_EMCRH= EMRH; - } - - for(i=0; i<32; i++) - { - if((EMR>>i)&1) - printf(" EDMA Channel %d event missed.\n", i); - if((EMRH>>i)&1) - printf(" EDMA Channel %d event missed.\n", i+32); - } - - for(i=0; i<8; i++) - { - if((QEMR>>i)&1) - printf(" QDMA Channel %d event missed.\n", i); - } - - for(i=0; i<4; i++) - { - if((CCERR>>i)&1) - printf(" Queue %d Watermark/threshold has been exceeded.\n", i); - } - - if(CCERR&CSL_TPCC_TPCC_CCERR_TCCERR_MASK) - puts(" Total number of allowed TCCs has been reached."); - -} -/***************************************************************************** - Prototype : EDMA_TC_error_handler - Description : Edma transfer controller error processing - Input : CSL_TptcRegs * edmaTCRegs - Output : None - Return Value : - - History : - 1.Date : 2012/11/7 - Author : Brighton Feng - Modification : Created function - -*****************************************************************************/ -void EDMA_TC_error_handler(CSL_TptcRegs * edmaTCRegs) -{ - Uint32 ERRSTAT, ERRDET, STAT; - - //read error status - ERRSTAT= edmaTCRegs->TPTC_ERRSTAT; - ERRDET= edmaTCRegs->TPTC_ERRDET; - exception_record.status.ext_sts.info.edma.TC_info.ERRSTAT=ERRSTAT ; - exception_record.status.ext_sts.info.edma.TC_info.ERRDET= ERRDET; - - //clear error - edmaTCRegs->TPTC_ERRCLR= ERRSTAT; - - if(ERRSTAT&CSL_TPTC_TPTC_ERRSTAT_MMRAERR_MASK) - puts(" User attempted to read or write to an invalid address in configuration memory map."); - if(ERRSTAT&CSL_TPTC_TPTC_ERRSTAT_TRERR_MASK) - puts(" TR detected that violates constant addressing mode transfer (SAM or DAM is set) alignment rules or has ACNT or BCNT== 0."); - if(ERRSTAT&CSL_TPTC_TPTC_ERRSTAT_BUSERR_MASK) - { - puts(" EDMA3TC has detected an error at source or destination address."); - - STAT= ERRDET&CSL_TPTC_TPTC_ERRDET_STAT_MASK; - - if(STAT>=8) - printf(" write error (%d). ",STAT); - else if(STAT>=1) - printf(" read error (%d). ",STAT); - else - printf(" no error!?"); - - printf("TCC= %d. TCINTEN= %d. TCCHEN= %d\n", - (ERRDET&CSL_TPTC_TPTC_ERRDET_TCC_MASK)>>CSL_TPTC_TPTC_ERRDET_TCC_SHIFT, - (ERRDET&CSL_TPTC_TPTC_ERRDET_TCINTEN_MASK)>>CSL_TPTC_TPTC_ERRDET_TCINTEN_SHIFT, - (ERRDET&CSL_TPTC_TPTC_ERRDET_TCCHEN_MASK)>>CSL_TPTC_TPTC_ERRDET_TCCHEN_SHIFT); - } - -} -/***************************************************************************** - Prototype : EDMA_error_handler - Description : EDMA error processing function - Input : Uint32 edmaNum - Uint32 errorFlag - error flag bit fields are defined as below - (follow the sequence in CIC) - 0 EDMACC_ERRINT EDMA3CC error interrupt - 2 EDMATC_ERRINT0 EDMA3TC0 error interrupt - 3 EDMATC_ERRINT1 EDMA3TC1 error interrupt - 4 EDMATC_ERRINT2 EDMA3TC2 error interrupt - 5 EDMATC_ERRINT3 EDMA3TC3 error interrupt - Output : None - Return Value : - - History : - 1.Date : 2012/10/28 - Author : Brighton Feng - Modification : Created function - -*****************************************************************************/ -void EDMA_error_handler(Uint32 edmaNum, Uint32 errorFlag) -{ - int i; - - printf(" EDMA module %d error\n", edmaNum); - if(errorFlag&1) - EDMA_CC_error_handler(edmaNum); - - errorFlag >>= 2; - - for(i=0; i<4; i++) - { - if(errorFlag&(1<MPLKCMD = (1<MPLK[i] = mem_prot_key[i]; - } - - /*3. Write a 1 to the LOCK field of the MPLKCMD register. This engages the lock.*/ - gpCGEM_regs->MPLKCMD = (1<MPLKSTAT&CSL_CGEM_MPLKSTAT_LK_MASK)); -} - -/***************************************************************************** - Prototype : unlock_mem_prot_regs - Description : unlock memory protection registers - Input : None - Output : None - Return Value : - - History : - 1.Date : 2010/12/12 - Author : Brighton Feng - Modification : Created function - -*****************************************************************************/ -#pragma CODE_SECTION (unlock_mem_prot_regs, ".text:Core_MPAX") -void unlock_mem_prot_regs() -{ - int i; - - /*1. Write a 1 to the KEYR field in the MPLKCMD register. This resets some internal - status for the MPLK0 through the MPLK3 registers.*/ - gpCGEM_regs->MPLKCMD = (1<MPLK[i] = mem_prot_key[i]; - } - - /*3. Write a 1 to the UNLOCK field in the MPLKCMD register. If the key written in - step 2 matches the stored key, the hardware disengages the lock. If the key written - in step 2 does not match, the hardware signals an exception. The hardware - reports the fault address as the address of the MPLKCMD register.*/ - gpCGEM_regs->MPLKCMD = (1<MPLKSTAT&CSL_CGEM_MPLKSTAT_LK_MASK)); -} - -/***************************************************************************** - Prototype : L1_MPPA_setup - Description : setup the memory protection for local L1 memory - Input : volatile Uint32 MPPA_regs[], Uint32 MPPA[] - Output : None - Return Value : - -usage example: - Uint32 MPPA[16]= - { - MP_LOCAL|MP_SR|MP_UR, //page 0 for read only - MP_LOCAL|MP_SR|MP_SW|MP_UR|MP_UW, //page 1 for read/write - ...... - } - ...... - L1_MPPA_setup(gpCGEM_regs->L1PMPPA, MPPA); - - History : - 1.Date : 2012/12/6 - Author : Brighton Feng - Modification : Created function - -*****************************************************************************/ -void L1_MPPA_setup(volatile Uint32 MPPA_regs[], Uint32 MPPA[]) -{ - int i; - - if(gpCGEM_regs->MPLKSTAT&CSL_CGEM_MPLKSTAT_LK_MASK) - unlock_mem_prot_regs(); - - /*clear any memory protection fault*/ - gpCGEM_regs->L1PMPFCR = 1; - gpCGEM_regs->L1DMPFCR = 1; - - /*setup the memory protection attributes for 32 pages*/ - for(i=0; i<16; i++) - { - MPPA_regs[i] = MPPA[i]; - } - - lock_mem_prot_regs(); -} - -/***************************************************************************** - Prototype : L1P_memory_protection_cfg - Description : config "AccessPermisionMask" for L1P - Input : Uint32 AccessPermisionMask - Output : None - Return Value : -*****************************************************************************/ -void L1P_memory_protection_cfg(Uint32 AccessPermisionMask) -{ - int i; - - if(gpCGEM_regs->MPLKSTAT&CSL_CGEM_MPLKSTAT_LK_MASK) - unlock_mem_prot_regs(); - - /*clear any memory protection fault*/ - gpCGEM_regs->L1PMPFCR = 1; - - /*set L1P only for cacheable local execution, disable all external access*/ - for(i=0; i<16; i++) - { - gpCGEM_regs->L1PMPPA[i] = AccessPermisionMask; - } - - lock_mem_prot_regs(); -} - -/***************************************************************************** - Prototype : L1D_memory_protection_cfg - Description : config "AccessPermisionMask" for L1P - Input : Uint32 AccessPermisionMask - Output : None - Return Value : -*****************************************************************************/ -void L1D_memory_protection_cfg(Uint32 AccessPermisionMask) -{ - int i; - - if(gpCGEM_regs->MPLKSTAT&CSL_CGEM_MPLKSTAT_LK_MASK) - unlock_mem_prot_regs(); - - /*clear any memory protection fault*/ - gpCGEM_regs->L1DMPFCR = 1; - - /*set L1P only for cacheable local execution, disable all external access*/ - for(i=0; i<16; i++) - { - gpCGEM_regs->L1DMPPA[i] = AccessPermisionMask; - } - - lock_mem_prot_regs(); -} - -/***************************************************************************** - Prototype : L1_cache_protection - Description : protect L1 as cache - Input : None - Output : None - Return Value : - - History : - 1.Date : 2012/10/28 - Author : Brighton Feng - Modification : Created function - -*****************************************************************************/ -void L1_cache_protection() -{ - /*set L1P only for cacheable local execution, disable all external access*/ - L1P_memory_protection_cfg(0); - - /*set L1D only for cacheable local read/write, disable all external access*/ - L1D_memory_protection_cfg(0); -} - - -/***************************************************************************** - Prototype : LL2_MPPA_setup - Description : setup the memory protection for local L2 memory - Input : Uint32 MPPA[] - Output : None - Return Value : -usage example: - Uint32 MPPA[32]= - { - MP_LOCAL|MP_SX|MP_UX, //page 0 for local code only - MP_LOCAL|MP_SR|MP_SW|MP_UR|MP_UW, //page 1 for local data only - ...... - } - ...... - LL2_MPPA_setup(MPPA); - - History : - 1.Date : 2012/10/5 - Author : Brighton Feng - Modification : Created function - -*****************************************************************************/ -void LL2_MPPA_setup(Uint32 MPPA[]) -{ - int i; - - if(gpCGEM_regs->MPLKSTAT&CSL_CGEM_MPLKSTAT_LK_MASK) - unlock_mem_prot_regs(); - - /*clear any memory protection fault*/ - gpCGEM_regs->L2MPFCR = 1; - - /*setup the memory protection attributes for 32 pages*/ - for(i=0; i<32; i++) - { - gpCGEM_regs->L2MPPA[i] = MPPA[i]; - } - - lock_mem_prot_regs(); -} - -/***************************************************************************** - Prototype : LL2_Memory_Protection_cfg - Description : config "AccessPermisionMask" for local L2 memory section from - "startAddress" with "byteCount" size - Input : Uint32 startAddress - Uint32 byteCount - Uint32 AccessPermisionMask - Output : None - Return Value : - - History : - 1.Date : 2012/10/5 - Author : Brighton Feng - Modification : Created function - -*****************************************************************************/ -void LL2_Memory_Protection_cfg(Uint32 startAddress, - Uint32 byteCount, Uint32 AccessPermisionMask) -{ - int i; - Uint32 uiEndAddress; - Uint32 uiPageIndex, uiNumPages, uiPageSize, uiPageAddressMask, uiPageShift; - TDSP_Board_Type DSP_Board_Type; - - if(gpCGEM_regs->MPLKSTAT&CSL_CGEM_MPLKSTAT_LK_MASK) - unlock_mem_prot_regs(); - - DSP_Board_Type = KeyStone_Get_dsp_board_type(); - - /*L2 memory protection size is 32KB for TCI6614, C6670, - it is 16KB for C6678*/ - uiPageSize= 32*1024; - uiPageAddressMask= 32*1024-1; - uiPageShift= 15; - if(C6678_EVM == DSP_Board_Type) - { - uiPageSize= 16*1024; - uiPageAddressMask= 16*1024-1; - uiPageShift= 14; - } - - if(startAddress>=0x10800000) - { - printf("LL2 memory protection start Address 0x%x is not a local address\n", - startAddress); - startAddress &= 0xFFFFFF; /*convert to local address*/ - } - uiEndAddress= startAddress+ byteCount; - - if(startAddress&uiPageAddressMask) - { - printf("LL2 memory protection start Address 0x%x does not align to page boundary\n", - startAddress); - startAddress &= (~uiPageAddressMask); - } - uiPageIndex= (startAddress-0x800000)>>uiPageShift; - - byteCount= uiEndAddress- startAddress; - if(byteCount&uiPageAddressMask) - { - printf("LL2 memory protection section size 0x%x is not multiple of page size\n", - byteCount); - byteCount = (byteCount+uiPageSize)&(~uiPageAddressMask); - } - uiNumPages= byteCount>>uiPageShift; - - for(i= 0; iL2MPPA[uiPageIndex+i] = AccessPermisionMask; - - lock_mem_prot_regs(); -} - -/***************************************************************************** - Prototype : KeyStone_CorePac_AID_map - Description : map CorePac AID to PrivID: - map_table[0] assign the PrivID for AID0, - map_table[1] assign the PrivID for AID1 - ...... - map_table[5] assign the PrivID for AID5 - Input : Uint8 map_table[] - Output : None - Return Value : - - History : - 1.Date : 2012/10/5 - Author : Zhan - Modification : Created function - -*****************************************************************************/ -void KeyStone_CorePac_AID_map(Uint8 map_table[]) -{ - int i; - Uint32 *PAMAP= (Uint32 *)&(gpCGEM_regs->PAMAP0); - - /*map all PrivID to AIDx by default*/ - for(i=0; i<16; i++) - PAMAP[i]= CSL_CGEM_PAMAP0_AID_MASK; - - /*map AID0~AID5*/ - for(i=0; i<6; i++) - { - if(map_table[i]<16) /*PrivID must be less than 16*/ - PAMAP[map_table[i]]= i; - } -} - -/***************************************************************************** - Prototype : KeyStone_PrivID_Remap - Description : privilege ID remap to AID - Input : int privID - int AID - Output : None - Return Value : - - History : - 1.Date : 2012/10/5 - Author : Zhan - Modification : Created function - -*****************************************************************************/ -void KeyStone_PrivID_Remap(int privID, int AID) -{ - volatile unsigned int * pamapReg = NULL; - unsigned int val = 0; - - pamapReg = (volatile unsigned int *)(&gpCGEM_regs->PAMAP0 + privID); - - if(AID >= MAX_AID_NUM) - AID = 0; - val = *pamapReg; - - val &= (~CSL_CGEM_PAMAP0_AID_MASK); - - val |= ((AID<>4)) - { - printf("Segment replacement address 0x%x does not start from power-of-2 boundary corresponds to segment size 0x%x.\n", - RADDR, SegementSize); - RADDR &= (~(SegSizeMask>>4)); - printf("Extended replacement address to 0x%x.\n", RADDR); - } - - MPAX_regs->MPAXH= BADDR|(SegSizeBits-1); - MPAX_regs->MPAXL= RADDR|AccessPermisionMask; - -} - -/***************************************************************************** - Prototype : KeyStone_XMC_MPAX_setup - Description : configure multiple MPAX segments in XMC with a configuration - table. - Please note, the code of this function or the data used by this function - (stack, parameters...) can not be put in the segment that will be modified - by this function. Normally, to put this function and its related data in - LL2 is a good idea. - Input : MPAX_Config MPAX_cfg[] - Uint32 firstSeg - Uint32 numSegs - Output : None - Return Value : - - History : - 1.Date : 2012/10/15 - Author : Brighton Feng - Modification : Created function - -*****************************************************************************/ -#pragma CODE_SECTION (KeyStone_XMC_MPAX_setup, ".text:Core_MPAX") -void KeyStone_XMC_MPAX_setup(MPAX_Config MPAX_cfg[], - Uint32 firstSeg, Uint32 numSegs) -{ - int i; - - if(firstSeg >= 16) - { - printf("The XMC MPAX segment number %d >= 16, not supported.\n ", firstSeg); - return; - } - - if(gpCGEM_regs->MPLKSTAT&CSL_CGEM_MPLKSTAT_LK_MASK) - unlock_mem_prot_regs(); - - /*CAUTION: - A MPAX segment can only be modified when there is no access to the space - of this segment. Any data in cache or prefetch buffer from the space of this - segment must be writeback and invalidated before the segment modification. - It is recommended to configure the MPAX at the very beginning of application - software before any shared memory is used. Code and data for CorePac MPAX - configuration should be allocated in LL2. - If a MPAX segment must be modified on-the-fly, the safer way is, to write - the new configuration to a unused higher segment, and then clear the old - segment. This is based on the fact that higher numbered segments take - precedence over lower numbered segments. */ - CACHE_wbInvAllL2(CACHE_WAIT); - CSL_XMC_invalidatePrefetchBuffer(); - _mfence(); - _mfence(); //ensure all writeback invalidate have completed. - - for(i=numSegs-1; i>=0 ; i--) - { - KeyStone_MPAX_seg_setup((MPAX_Regs *)&gpXMC_regs->XMPAX[firstSeg+i], - MPAX_cfg[i].BADDR, MPAX_cfg[i].RADDR, - MPAX_cfg[i].SegementSize, MPAX_cfg[i].AccessPermisionMask); - } - - lock_mem_prot_regs(); -} - -/***************************************************************************** - Prototype : KeyStone_SMS_MPAX_setup - Description : configure multiple MPAX segments in SMS of MSMC with a conf- - iguration table - Input : MPAX_Config MPAX_cfg[] - Uint32 firstSeg - Uint32 numSegs - Uint32 PrivID - Output : None - Return Value : - - History : - 1.Date : 2012/10/15 - Author : Brighton Feng - Modification : Created function - -*****************************************************************************/ -void KeyStone_SMS_MPAX_setup(MPAX_Config MPAX_cfg[], - Uint32 firstSeg, Uint32 numSegs, Uint32 PrivID) -{ - int i; - - if( gpMSMC_regs->SMS_MPAX_LCKSTAT&(1<=0 ; i--) - KeyStone_MPAX_seg_setup( - (MPAX_Regs *)&gpMSMC_regs->SMS_MPAX_PER_PRIVID[PrivID].SMS[firstSeg+i], - MPAX_cfg[i].BADDR, MPAX_cfg[i].RADDR, - MPAX_cfg[i].SegementSize, MPAX_cfg[i].AccessPermisionMask); - - CSL_MSMC_lockSMS(PrivID); -} - -/***************************************************************************** - Prototype : KeyStone_SES_MPAX_setup - Description : configure multiple MPAX segments in SES of MSMC with a conf- - iguration table - Input : MPAX_Config MPAX_cfg[] - Uint32 firstSeg - Uint32 numSegs - Uint32 PrivID - Output : None - Return Value : - - History : - 1.Date : 2012/10/15 - Author : Brighton Feng - Modification : Created function - -*****************************************************************************/ -void KeyStone_SES_MPAX_setup(MPAX_Config MPAX_cfg[], - Uint32 firstSeg, Uint32 numSegs, Uint32 PrivID) -{ - int i; - - if( gpMSMC_regs->SES_MPAX_LCKSTAT&(1<=0 ; i--) - KeyStone_MPAX_seg_setup( - (MPAX_Regs *)&gpMSMC_regs->SES_MPAX_PER_PRIVID[PrivID].SES[firstSeg+i], - MPAX_cfg[i].BADDR, MPAX_cfg[i].RADDR, - MPAX_cfg[i].SegementSize, MPAX_cfg[i].AccessPermisionMask); - - CSL_MSMC_lockSES(PrivID); -} - -/***************************************************************************** - Prototype : KeyStone_MSMC_MP_interrupt_en - Description : Enable MSMC Memory protection error interrupt for PrivIDs - indicated by "PRIVID_MASK" - Input : Uint32 PRIVID_MASK - Output : None - Return Value : - - History : - 1.Date : 2012/10/15 - Author : Zhan - Modification : Created function - -*****************************************************************************/ -void KeyStone_MSMC_MP_interrupt_en(Uint32 PRIVID_MASK) -{ - if(gpMSMC_regs->CFGLCKSTAT&CSL_MSMC_CFGLCKSTAT_WSTAT_MASK) - CSL_MSMC_unlockNonMPAX(); - - /*clear MP fault record*/ - gpMSMC_regs->SMPFCR = 1; - - /*clear interrupt error status flag*/ - gpMSMC_regs->SMIRC = (PRIVID_MASK)<SMIESTAT |= (PRIVID_MASK<> - CSL_CGEM_L2MPFSR_FID_SHIFT; - - printf(" memory protection exception caused by master with ID %d at 0x%x\n", - master_id, MPFAR); - } - - if (MPFSR & CSL_CGEM_L2MPFSR_UX_MASK) { - puts(" User Execute violation"); - } - if (MPFSR & CSL_CGEM_L2MPFSR_UW_MASK) { - puts(" User Write violation"); - } - if (MPFSR & CSL_CGEM_L2MPFSR_UR_MASK) { - puts(" User Read violation"); - } - if (MPFSR & CSL_CGEM_L2MPFSR_SX_MASK) { - puts(" Supervisor Execute violation"); - } - if (MPFSR & CSL_CGEM_L2MPFSR_SW_MASK) { - puts(" Supervisor Write violation"); - } - if (MPFSR & CSL_CGEM_L2MPFSR_SR_MASK) { - puts(" Supervisor Read violation"); - } - -} - -/***************************************************************************** - Prototype : KeyStone_MSMC_protection_exception_handler - Description : MSMC memory protection processing - Input : None - Output : None - Return Value : -*****************************************************************************/ -void KeyStone_MSMC_protection_exception_handler() -{ - unsigned int master_id; - unsigned int priv_id; - unsigned int address; - unsigned int NM; - - address = gpMSMC_regs->SMPFAR; - - master_id = (gpMSMC_regs->SMPFR&CSL_MSMC_SMPFR_FMSTID_MASK)>> - CSL_MSMC_SMPFR_FMSTID_SHIFT; - priv_id = (gpMSMC_regs->SMPFR&CSL_MSMC_SMPFR_FPID_MASK)>> - CSL_MSMC_SMPFR_FPID_SHIFT; - - exception_record.status.ext_sts.info.memory.fault_address= address; - exception_record.status.ext_sts.info.memory.fault_status.SMPFR= gpMSMC_regs->SMPFR; - - NM = (gpMSMC_regs->SMPFXR & CSL_MSMC_SMPFXR_NM_MASK) >> CSL_MSMC_SMPFXR_NM_SHIFT; - - printf(" memory protection exception caused by master %d (PrivID= %d) at address 0x%x\n", - master_id, priv_id, address); - - if(1 == NM) - { - printf(" Fault is caused by the address not matching any of the segment BADDR\n"); - } - - if(gpMSMC_regs->CFGLCKSTAT&CSL_MSMC_CFGLCKSTAT_WSTAT_MASK) - CSL_MSMC_unlockNonMPAX(); - /*clear fault record*/ - gpMSMC_regs->SMPFCR = 1; - /*clear interrupt error status flag*/ - gpMSMC_regs->SMIRC = (1<PROG_START_ADDRESS = uiStartAddress; - MPPA_regs->PROG_END_ADDRESS = uiEndAddress; - MPPA_regs->PROG_MPPA = AccessPermisionMask; -} - -/***************************************************************************** - Prototype : KeyStone_MPU_setup - Description : peripherals MPU ranges configuration - Input : Uint32 uiMPU_num: number of the MPU to be setup - MPU_Range_Config MPU_cfg[]: MPU ranges configuration table - Uint32 numRangeCfg: number of ranges to be configured - Output : None - Return Value : - - History : - 1.Date : 2012/12/15 - Author : Brighton Feng - Modification : Created function -*****************************************************************************/ -void KeyStone_MPU_setup(Uint32 uiMPU_num, - MPU_Range_Config MPU_cfg[], Uint32 numRangeCfg) -{ - int i; - unsigned int mpuNumProgmableRange; - CSL_MpuRegs * mpuRegs; - - /*For Turbo Nyquist, add following code to modify initial value, - Or user can modify the initail values directly*/ - if(5==uiMPU_num) - TN_MPU5_constant(); - - mpuRegs= gpMPU_regs[uiMPU_num]; - - mpuNumProgmableRange = (mpuRegs->CONFIG & CSL_MPU_CONFIG_NUM_PROG_MASK)>>CSL_MPU_CONFIG_NUM_PROG_SHIFT; - if(mpuNumProgmableRange == 0) - { - mpuNumProgmableRange = 16; - } - - if(numRangeCfg>mpuNumProgmableRange) - { - printf("MPU %d programmable ranges %d < %d.\n", - uiMPU_num, mpuNumProgmableRange, numRangeCfg); - numRangeCfg=mpuNumProgmableRange; - } - else if(numRangeCfg gstruMpuAddrRange[uiMPU_num].EndAddr) ) - { - printf("The configuration address is out of MPU %d protection range\n", - uiMPU_num); - continue; - } - - KeyStone_MPU_range_setup(&mpuRegs->PROG_REGION[i], - MPU_cfg[i].StartAddr, MPU_cfg[i].EndAddr, - MPU_cfg[i].AccessPermisionMask); - - } - - //clear unused ranges - for( ;iPROG_REGION[i].PROG_MPPA = 0; - } - - //clear status - mpuRegs->FAULT_CLEAR = 1; - mpuRegs->INT_ENABLED_STATUS_CLEAR = - CSL_MPU_INT_ENABLED_STATUS_CLEAR_ENABLED_ADDR_ERR_MASK - |CSL_MPU_INT_ENABLED_STATUS_CLEAR_ENABLED_PROT_ERR_MASK; - - /* enable the interrupt */ - mpuRegs->INT_ENABLE = CSL_MPU_INT_ENABLE_ADDR_ERR_EN_MASK - | CSL_MPU_INT_ENABLE_PROT_ERR_EN_MASK; - - return; -} - -/***************************************************************************** - Prototype : KeyStone_MPU_MPPA_modify - Description : search the range which match a address and then modify - the access permission of that range. - Input : Uint32 uiMPU_num: number of the MPU to be modifed - Uint32 uiAddress: address which need modify permision - Uint32 AccessPermisionMask: permission mask for that range - Output : None - Return Value : - - History : - 1.Date : 2012/12/13 - Author : Brighton Feng - Modification : Created function -*****************************************************************************/ -void KeyStone_MPU_MPPA_modify(Uint32 uiMPU_num, - Uint32 uiAddress, Uint32 AccessPermisionMask) -{ - int i; - unsigned int mpuNumProgmableRange; - CSL_MpuRegs * mpuRegs; - - /*For Turbo Nyquist, add following code to modify initial value, - Or user can modify the initail values directly*/ - if(5==uiMPU_num) - TN_MPU5_constant(); - - mpuRegs= gpMPU_regs[uiMPU_num]; - - mpuNumProgmableRange = (mpuRegs->CONFIG & CSL_MPU_CONFIG_NUM_PROG_MASK)>>CSL_MPU_CONFIG_NUM_PROG_SHIFT; - if(mpuNumProgmableRange == 0) - { - mpuNumProgmableRange = 16; - } - - /*search through all ranges*/ - for(i=0; i< mpuNumProgmableRange; i++) - { - /*match with one range*/ - if((uiAddress >= mpuRegs->PROG_REGION[i].PROG_START_ADDRESS) - &&(uiAddress <= mpuRegs->PROG_REGION[i].PROG_END_ADDRESS)) - { - mpuRegs->PROG_REGION[i].PROG_MPPA = AccessPermisionMask; - return; - } - } - - printf("address 0x%08x does not match any range in MPU %d\n", - uiAddress, uiMPU_num); - - return; -} - -/***************************************************************************** - Prototype : KeyStone_MPU_interrupts_enable - Description : enable the all MPU interrupts - Input : None - Output : None - Return Value : - - History : - 1.Date : 2012/10/28 - Author : Brighton Feng - Modification : Created function - -*****************************************************************************/ -void KeyStone_MPU_interrupt_enable(Uint32 uiMPU_num) -{ - if((gpMPU_regs[uiMPU_num]->REVISION&0xFFFF0000)!= - (CSL_MPU_REVISION_RESETVAL&0xFFFF0000)) - { - printf("Can't read MPU%d ID register, make sure corresponding power domain is enabled.", uiMPU_num); - return; - } - - gpMPU_regs[uiMPU_num]->FAULT_CLEAR = 1; - gpMPU_regs[uiMPU_num]->INT_ENABLED_STATUS_CLEAR = - CSL_MPU_INT_ENABLED_STATUS_CLEAR_ENABLED_ADDR_ERR_MASK - |CSL_MPU_INT_ENABLED_STATUS_CLEAR_ENABLED_PROT_ERR_MASK; - gpMPU_regs[uiMPU_num]->INT_ENABLE = CSL_MPU_INT_ENABLE_ADDR_ERR_EN_MASK - |CSL_MPU_INT_ENABLE_PROT_ERR_EN_MASK; - -} -void KeyStone_MPU_interrupts_enable() -{ - int i; - TDSP_Board_Type DSP_Board_Type = KeyStone_Get_dsp_board_type(); - - TN_MPU5_constant(); - - for(i=0; i<4; i++) - { - KeyStone_MPU_interrupt_enable(i); - } - - if((C6670_EVM== DSP_Board_Type) - ||(TCI6614_EVM== DSP_Board_Type)) - { - for(i=4; i<6; i++) - { - /*MPU5 (for BCP) of TCI6614 is only accessible - when BCP is enabled through PSC*/ - if((5==i)&&(TCI6614_EVM== DSP_Board_Type)&& - ((CSL_PSC_getPowerDomainState(5) != PSC_PDSTATE_ON) || - (CSL_PSC_getModuleState (12) != PSC_MODSTATE_ENABLE))) - { - puts("Enable power domain for MPU5 before configure it."); - continue; - } - - KeyStone_MPU_interrupt_enable(i); - } - } - - if(TCI6614_EVM== DSP_Board_Type) - { - for(i=6; i<8; i++) - { - KeyStone_MPU_interrupt_enable(i); - } - } - - return; -} - -char * Peri_MPU_err_type_str[]= -{ - "User execution fault!", - "User write fault!", - "User read fault!", - "Supervisor execution fault!", - "Supervisor write fault!", - "Supervisor read fault!" -}; - -char * Ns_str[]= -{ - "secure", - "non-secure" -}; -/***************************************************************************** - Prototype : KeyStone_peripherals_MPU_fault_status - Description : Print the MPU error information - Input : unsigned int uwFltStatus - unsigned int uwFltAddr - Output : None - Return Value : -*****************************************************************************/ -void KeyStone_peripherals_MPU_fault_status(unsigned int uwFltStatus, - unsigned int uwFltAddr) -{ - unsigned int MSTID; - unsigned int PRIVID; - unsigned int NS; - unsigned int FaultType; - unsigned int BitsCnt; - - MSTID = (uwFltStatus & CSL_MPU_FAULT_STATUS_MSTID_MASK)>>CSL_MPU_FAULT_STATUS_MSTID_SHIFT; - PRIVID = (uwFltStatus & CSL_MPU_FAULT_STATUS_PRIVID_MASK)>>CSL_MPU_FAULT_STATUS_PRIVID_SHIFT; - NS = (uwFltStatus & CSL_MPU_FAULT_STATUS_NS_MASK)>>CSL_MPU_FAULT_STATUS_NS_SHIFT; - printf(" The MSTID %d (PRIVID %d) triggered MPU error at 0x%x with %s access\n", - MSTID, PRIVID, uwFltAddr, Ns_str[NS]); - - FaultType = (uwFltStatus & CSL_MPU_FAULT_STATUS_FAULT_TYPE_MASK) >> CSL_MPU_FAULT_STATUS_FAULT_TYPE_SHIFT; - if(1==(_dotpu4(_bitc4(FaultType), 0x01010101))) - { - BitsCnt= 31 - _lmbd(1, FaultType); - printf(" %s\n",Peri_MPU_err_type_str[BitsCnt]); - } - else if(0x3F == FaultType) - { - puts(" Relaxed cache line fill fault!"); - } - else if(0x12 == FaultType) - { - puts(" Relaxed cache write back fault!"); - } -} -/***************************************************************************** - Prototype : KeyStone_peripherals_MPU_excepiton_handler - Description : peripheral MPU processing - Input : Uint32 uwMpuNum - Output : None - Return Value : -*****************************************************************************/ -void KeyStone_peripherals_MPU_excepiton_handler(Uint32 uwMpuNum) -{ - Uint32 uwStatus; - Uint32 uwFltAddr; - Uint32 uwFltStatus; - CSL_MpuRegs *pstruMpuRegs= gpMPU_regs[uwMpuNum]; - - uwStatus = pstruMpuRegs->INT_ENABLED_STATUS_CLEAR; - if(uwStatus & 0x2) - { - printf(" MPU %d address violation error\n", uwMpuNum); - pstruMpuRegs->INT_ENABLED_STATUS_CLEAR = 2; - } - - if(uwStatus & 0x1) - { - printf(" MPU %d protection violation error\n", uwMpuNum); - pstruMpuRegs->INT_ENABLED_STATUS_CLEAR = 1; - } - - uwFltAddr = pstruMpuRegs->FAULT_ADDRESS; - uwFltStatus = pstruMpuRegs->FAULT_STATUS; - exception_record.status.ext_sts.info.memory.fault_address= uwFltAddr; - exception_record.status.ext_sts.info.memory.fault_status.MPU_FAULT_STATUS= uwFltStatus; - - KeyStone_peripherals_MPU_fault_status(uwFltStatus,uwFltAddr); - pstruMpuRegs->FAULT_CLEAR = 1; - - pstruMpuRegs->EOI = 0; -} - - -/*======================memory EDC=====================================*/ -/***************************************************************************** - Prototype : KeyStone_SL2_EDC_enable - Description : Enable MSMC EDC - Input : scrubCnt, number of MSMC clock cycles between scrubbing - Output : None - Return Value : - - History : - 1.Date : 2012/10/15 - Author : Brighton Feng - Modification : Created function - -*****************************************************************************/ -void KeyStone_SL2_EDC_enable(Uint32 scrubCnt) -{ - if(gpMSMC_regs->CFGLCKSTAT&CSL_MSMC_CFGLCKSTAT_WSTAT_MASK) - CSL_MSMC_unlockNonMPAX(); - - /*Software must wait for the PRR (Parity RAM Ready) bit before making - the first read access to MSMC RAM after reset.*/ - while(0==(gpMSMC_regs->SMEDCC&CSL_MSMC_SMEDCC_PRR_MASK)); - - /* set scrubbing period value */ - if(scrubCnt>255) - scrubCnt= 255; - CSL_MSMC_setCounterBankRefreshRead(scrubCnt); //the scrubbing engine works every scrubCnt*1024 cycle*/ - - /* clear EDC errors and enable EDC event*/ - gpMSMC_regs->SMIRC = 0xf; - gpMSMC_regs->SMIESTAT |= (CSL_MSMC_SMIESTAT_NCSIE_MASK - | CSL_MSMC_SMIESTAT_CSIE_MASK - | CSL_MSMC_SMIESTAT_NCEIE_MASK - | CSL_MSMC_SMIESTAT_CEIE_MASK); - - //enable SL2 EDC - CSL_MSMC_setECM(1); - - CSL_MSMC_lockNonMPAX(); -} - -/***************************************************************************** - Prototype : KeyStone_SL2_EDC_interrupt_en - Description : Enable MSMC EDC error interrupt - Input : None - Output : None - Return Value : - - History : - 1.Date : 2012/10/15 - Author : Brighton Feng - Modification : Created function - -*****************************************************************************/ -void KeyStone_SL2_EDC_interrupt_en() -{ - if(gpMSMC_regs->CFGLCKSTAT&CSL_MSMC_CFGLCKSTAT_WSTAT_MASK) - CSL_MSMC_unlockNonMPAX(); - - /* clear EDC errors*/ - gpMSMC_regs->SMIRC = 0xf; - - /* Enable EDC error interrupt */ - gpMSMC_regs->SMIESTAT |= (CSL_MSMC_SMIESTAT_NCSIE_MASK - | CSL_MSMC_SMIESTAT_CSIE_MASK - | CSL_MSMC_SMIESTAT_NCEIE_MASK - | CSL_MSMC_SMIESTAT_CEIE_MASK); - - CSL_MSMC_lockNonMPAX(); -} - -/***************************************************************************** - Prototype : LL2_EDC_setup - Description : Eenable LL2 EDC and scrub whole LL2 - Input : None - Output : None - Return Value : - - History : - 1.Date : 2012/10/10 - Author : Jane - Modification : Created function - - 2.Date : 2012/10/20 - Author : Brighton Feng - -*****************************************************************************/ -void LL2_EDC_setup() -{ - int i; - unsigned int uiByteCnt= 512*1024; - TDSP_Board_Type DSP_Board_Type; - - /* 1. Disable the EDC */ - CSL_CGEM_disableL2EDC(); - - /* 2. Clear any EDC errors */ - CSL_CGEM_clearL2EDCErrorStatus(1, 1, 1, 1); - - /* 3. Memory Scrubbing with IDMA, generate the parity bits*/ - DSP_Board_Type = KeyStone_Get_dsp_board_type(); - if((DUAL_NYQUIST_EVM == DSP_Board_Type) - ||(C6670_EVM == DSP_Board_Type) - ||(TCI6614_EVM == DSP_Board_Type)) - { - uiByteCnt= 1024*1024; - } - - /*Each IDMA can transfer up to 65532 bytes, - here we transfer 32KB each time*/ - for(i=0; i< (uiByteCnt>>15); i++) - { - IDMA_copy((0x00800000 + i*(1<<15)), (0x00800000 + i*(1<<15)), - (1<<15), DMA_WAIT); - } - - /* 4. Enable the EDC*/ - CSL_CGEM_enableL2EDC(); - gpCGEM_regs->L2EDCEN= (1<= uiLL2EndAddress) - uiLL2_scrub_addr=0x800000; - -} - -/***************************************************************************** - Prototype : L1P_EDC_setup - Description : enable L1P ED and scrub whole L1P - Input : None - Output : None - Return Value : - - History : - 1.Date : 2012/10/10 - Author : Jane - Modification : Created function - - 2.Date : 2012/10/30 - Author : Brighton Feng -*****************************************************************************/ -void L1P_EDC_setup() -{ - Uint32 preL1PMPPA[16]; - - /* 1. Disable the EDC */ - CSL_CGEM_disablePMCErrorDetection(); - - /* 2. Clear any EDC errors */ - CSL_CGEM_clearPMCErrorDetectionStatus(1, 1); - - /* 3. Memory Scrubbing with IDMA, generate the parity bits*/ - memcpy(preL1PMPPA, (void *)gpCGEM_regs->L1PMPPA, 64);//save protection attributes - L1P_memory_protection_cfg(0xFFFF); //enable IDMA access to L1P - IDMA_copy(0x00E00000, 0x00E00000, 32*1024, DMA_WAIT); - L1_MPPA_setup(gpCGEM_regs->L1PMPPA, preL1PMPPA);//restore protection for L1 - - /* 4. Enable the EDC*/ - CSL_CGEM_enablePMCErrorDetection(); -} - -char * LL2_EDC_victim_err_str="LL2 victims"; -char * LL2_EDC_DMA_err_str= "DMA access"; -char * LL2_EDC_L1D_err_str= "L1D access"; -char * LL2_EDC_L1P_err_str= "L1P access"; - -/***************************************************************************** - Prototype : LL2_EDC_handler - Description : LL2 EDC exception/interrupt handler - Input : None - Output : None - Return Value : - - History : - 1.Date : 2012/10/28 - Author : Brighton Feng - Modification : Created function - -*****************************************************************************/ -void LL2_EDC_handler(Bool bCorrected) -{ - /* EDC error during the L1D access */ - Uint8 derr; - /* EDC error during the L1P access */ - Uint8 perr; - /* EDC error during the DMA access*/ - Uint8 dmaerr; - /* EDC error during the L2 victim occurred */ - Uint8 verr; - /* single bit or dual bit EDC error */ - Uint8 nerr; - - char *errStr; - Uint32 errAddr; - - /* Get the all LL2 error status */ - CSL_CGEM_getL2EDCErrorStatus(&derr, &perr, &dmaerr, &verr, &nerr); - - if(derr|perr|dmaerr|verr) - { - errAddr= gpCGEM_regs->L2EDADDR&CSL_CGEM_L2EDADDR_ADDR_MASK; - - exception_record.status.ext_sts.info.memory.fault_address= errAddr; - exception_record.status.ext_sts.info.memory.fault_status.L2EDSTAT= - gpCGEM_regs->L2EDSTAT; - - if(bCorrected) - { - printf(" LL2 EDC (correctable) at bit %d of ",(gpCGEM_regs->L2EDSTAT& - CSL_CGEM_L2EDSTAT_BITPOS_MASK)>>CSL_CGEM_L2EDSTAT_BITPOS_SHIFT); - - //scrub 64 bytes including the error address to correct the error - if(perr) //by L1P access - IDMA_copy(errAddr&0xFFFFFFC0, errAddr&0xFFFFFFC0, 64, DMA_WAIT); - else - { - volatile Uint32 * uipAddress= (volatile Uint32 *)(errAddr&0xFFFFFFC0); - /*read one word into a cache line, and write to make it dirty, - which will be automatically written back sooner or later*/ - *uipAddress= *uipAddress; - } - } - else - { - printf(" LL2 EDC error (non-correctable) at "); - } - errStr = (char *)(perr * (Uint32)LL2_EDC_L1P_err_str - + derr * (Uint32)LL2_EDC_L1D_err_str - + verr * (Uint32)LL2_EDC_victim_err_str - + dmaerr * (Uint32)LL2_EDC_DMA_err_str); - - printf("address 0x%x caused by %s.\n", - errAddr, - errStr); - - if(0==(gpCGEM_regs->L2EDADDR&CSL_CGEM_L2EDADDR_RAM_MASK)) - { - printf(" Error detected in Way %d of L2 cache\n", - (gpCGEM_regs->L2EDADDR&CSL_CGEM_L2EDADDR_WAY_MASK)>>CSL_CGEM_L2EDADDR_WAY_SHIFT); - } - - printf(" total non-correctable error number= %d, total correctable error number= %d.\n", - gpCGEM_regs->L2EDCNEC, gpCGEM_regs->L2EDCPEC); - - CSL_CGEM_clearL2EDCErrorStatus(derr, perr, dmaerr, verr); - } - else - { - puts(" Enter LL2 EDC handler, but no error flag is set!"); - } -} -/***************************************************************************** - Prototype : L1P_ED_handler - Description : L1P EDC processing - Input : None - Output : None - Return Value : - - History : - 1.Date : 2012/10/28 - Author : Brighton Feng - Modification : Created function - -*****************************************************************************/ -void L1P_ED_handler() -{ - Uint32 errAddr; - Uint8 errRAM; - - /* EDC error during DMA access */ - Uint8 dmaerr; - /* EDC error during program fetch access */ - Uint8 perr; - - /* Read PMC EDC status*/ - CSL_CGEM_getPMCErrorDetectionStatus(&dmaerr, &perr); - - if(perr|dmaerr) - { - CSL_CGEM_getPMCErrorInfo(&errAddr, &errRAM); - - exception_record.status.ext_sts.info.memory.fault_address= errAddr*32; - exception_record.status.ext_sts.info.memory.fault_status.L1PEDSTAT= - gpCGEM_regs->L1PEDSTAT; - - if(errRAM) - printf(" L1P RAM "); - else - printf(" L1P Cache "); - - printf("parity check error caused by "); - - if(perr == 1) - { - printf("program fetch "); - - /*flush wrong code in L1P. Code will be refetched from L2*/ - CACHE_invL1p((void *)NRP, 64, CACHE_WAIT); - } - else if(dmaerr == 1) - { - printf("DMA "); - } - printf("at address 0x%x\n", errAddr*32); - - CSL_CGEM_clearPMCErrorDetectionStatus(dmaerr,perr); - } -} - - -/***************************************************************************** - Prototype : KeyStone_SL2_EDC_handler - Description : SL2 EDC Processing - Input : None - Output : None - Return Value : - - History : - 1.Date : 2012/10/28 - Author : Brighton Feng - Modification : Created function - -*****************************************************************************/ -void KeyStone_SL2_EDC_handler() -{ - /* EDC correctable error during scrubbing cycle */ - Uint8 cses; - /* EDC non-correctable error during scrubbing cycle */ - Uint8 ncses; - /* EDC correctable error during SRAM access*/ - Uint8 cees; - /* EDC non-correctable error during SRAM access*/ - Uint8 ncees; - /* protection fault status*/ - Uint16 pfeStat; - - /* error address */ - Uint32 errAddr, bitPos, PrivID; - - if(gpMSMC_regs->CFGLCKSTAT&CSL_MSMC_CFGLCKSTAT_WSTAT_MASK) - CSL_MSMC_unlockNonMPAX(); - - CSL_MSMC_getPendingInterrupts(&pfeStat, &cees, &ncees, &cses, &ncses); - - exception_record.status.ext_sts.info.memory.fault_status.SMESTAT= - gpMSMC_regs->SMESTAT; - - if((cses == 1)||(ncses == 1)) - { - if(cses == 1) - { - /*scrubbing engine report address offset from 0*/ - errAddr = (gpMSMC_regs->SMCEA&0xFFFFFF)+0xc000000; - exception_record.status.ext_sts.info.memory.fault_address= errAddr; - - bitPos = (gpMSMC_regs->SMCEA&CSL_MSMC_SMCEA_ESYN_MASK) - >>CSL_MSMC_SMCEA_ESYN_SHIFT; - printf("SL2 Correctable error occurred at bit %d of address 0x%x by scrubbing\n", - bitPos, errAddr); - } - if(ncses == 1) - { - /*scrubbing engine report address offset from 0*/ - errAddr = gpMSMC_regs->SMNCEA+0xc000000; - exception_record.status.ext_sts.info.memory.fault_address= errAddr; - - printf("SL2 Non-correctable error occurred at address 0x%x by scrubbing\n", errAddr); - } - printf("%d correctable errors, %d non-correctable errors occurred during scrubbing.\n", - (gpMSMC_regs->SMSECC&CSL_MSMC_SMSECC_SCEC_MASK) - >>CSL_MSMC_SMSECC_SCEC_SHIFT, - (gpMSMC_regs->SMSECC&CSL_MSMC_SMSECC_SNCEC_MASK) - >>CSL_MSMC_SMSECC_SNCEC_SHIFT); - } - if(cees == 1) - { - volatile Uint32 scrubValue; - - errAddr = gpMSMC_regs->SMCERRAR; - exception_record.status.ext_sts.info.memory.fault_address= errAddr; - - //scrub the address to correct the error - scrubValue= *(volatile Uint32 *)errAddr; //touch to cach - *(volatile Uint32 *)errAddr= scrubValue; //make cache dirty - CACHE_wbInvL2((void *)errAddr, 32, CACHE_WAIT); - - bitPos = (gpMSMC_regs->SMCERRXR&CSL_MSMC_SMCERRXR_ESYN_MASK) - >>CSL_MSMC_SMCERRXR_ESYN_SHIFT; - PrivID = (gpMSMC_regs->SMCERRXR&CSL_MSMC_SMCERRXR_SEPID_MASK) - >>CSL_MSMC_SMCERRXR_SEPID_SHIFT; - printf("SL2 Correctable error occurred at bit %d of address 0x%x by PrivID %d ", - bitPos, errAddr, PrivID); - if(gpMSMC_regs->SMCERRXR&CSL_MSMC_SMCERRXR_SER_MASK) - printf("(not from C66x CorePacs)\n"); - else - printf("(from C66x CorePacs)\n"); - } - if(ncees ==1) - { - errAddr = gpMSMC_regs->SMNCERRAR; - exception_record.status.ext_sts.info.memory.fault_address= errAddr; - - PrivID = (gpMSMC_regs->SMNCERRXR&CSL_MSMC_SMNCERRXR_SEPID_MASK) - >>CSL_MSMC_SMNCERRXR_SEPID_SHIFT; - printf("SL2 Non-correctable error occurred at address 0x%x by PrivID %d ", - errAddr, PrivID); - if(gpMSMC_regs->SMNCERRXR&CSL_MSMC_SMNCERRXR_SER_MASK) - printf("(not from C66x CorePacs)\n"); - else - printf("(from C66x CorePacs)\n"); - } - - /* clear EDC error status */ - CSL_MSMC_clearRawInterruptStatus(0, cees,ncees, cses, ncses); - - CSL_MSMC_lockNonMPAX(); -} - -/*===============================Exception=============================*/ -//data structure to save exception info -Exception_Record exception_record; - -/*some exception events routed from CIC to INTC and then to exception moduel, -all these events are routed to one input of INTC*/ -Uint32 guwIntcCICExcEvtIdx= 95; /*INTC event number mapping to CIC exception events*/ -Uint32 gCIC_EXC_out_num = 15; //CIC output event number -Uint32 gCIC_EXC_EN_MASK[8]= {0,0,0,0,0,0,0,0}; -/***************************************************************************** - Prototype : KeyStone_CIC_exception_events_mapping - Description : CIC exception event mapping to the NMI external exception - Input : void - Output : None - Return Value : - - History : - 1.Date : 2012/10/5 - Author : Brighton Feng - Modification : Created function - - 2.Date : 2012/10/20 - Author : Zhan - Modification : Add event for TCI6614 - - 3.Date : 2012/10/28 - Author : Brighton Feng -*****************************************************************************/ -void KeyStone_CIC_exception_events_mapping(void) -{ - TDSP_Board_Type DSP_Board_Type= KeyStone_Get_dsp_board_type(); - -#if 1 - if(C6670_EVM==DSP_Board_Type - ||DUAL_NYQUIST_EVM==DSP_Board_Type - ||TCI6614_EVM==DSP_Board_Type) - { - gCIC_EXC_out_num= 15+16*DNUM; - } - else if(C6678_EVM==DSP_Board_Type) - { - if(DNUM<4) - gCIC_EXC_out_num= 7+8*DNUM; - else - { - gCIC_EXC_out_num= 7+8*(DNUM-4); - gpCIC_regs= gpCIC1_regs; - } - } - else - { - puts("Unknown DSP board type!"); - return; - } -#endif - - /*-----------------------CP_INTC configuration---------------------*/ - /* Disable Global host interrupts. */ - gpCIC_regs->GLOBAL_ENABLE_HINT_REG= 0; - - /* route following system events to CIC out (event 22 of INTC), and then to exception - TCI6614, C6670, C6678: - CIC: 0 EDMA3CC1 EDMACC_ERRINT EDMA3CC1 error interrupt - CIC: 2 EDMA3CC1 EDMATC_ERRINT0 EDMA3CC1 EDMA3TC0 error interrupt - CIC: 3 EDMA3CC1 EDMATC_ERRINT1 EDMA3CC1 EDMA3TC1 error interrupt - CIC: 4 EDMA3CC1 EDMATC_ERRINT2 EDMA3CC1 EDMA3TC2 error interrupt - CIC: 5 EDMA3CC1 EDMATC_ERRINT3 EDMA3CC1 EDMA3TC3 error interrupt - CIC: 16 EDMA3CC2 EDMACC_ERRINT EDMA3CC2 error interrupt - CIC: 18 EDMA3CC2 EDMATC_ERRINT0 EDMA3CC2 EDMA3TC0 error interrupt - CIC: 19 EDMA3CC2 EDMATC_ERRINT1 EDMA3CC2 EDMA3TC1 error interrupt - CIC: 20 EDMA3CC2 EDMATC_ERRINT2 EDMA3CC2 EDMA3TC2 error interrupt - CIC: 21 EDMA3CC2 EDMATC_ERRINT3 EDMA3CC2 EDMA3TC3 error interrupt - CIC: 32 EDMA3CC0 EDMACC_ERRINT EDMA3CC0 error interrupt - CIC: 34 EDMA3CC0 EDMATC_ERRINT0 EDMA3CC0 EDMA3TC0 error interrupt - CIC: 35 EDMA3CC0 EDMATC_ERRINT1 EDMA3CC0 EDMA3TC1 error interrupt - CIC: 99 MSMC_dedc_nc_error Non-correctable soft error detected on SRAM read - CIC: 100 MSMC_scrub_nc_error Non-correctable soft error detected during scrub cycle - CIC: 102 MSMC_mpf_error8 Memory protection fault indicators for each system master PrivID - CIC: 103 MSMC_mpf_error9 Memory protection fault indicators for each system master PrivID - CIC: 104 MSMC_mpf_error10 Memory protection fault indicators for each system master PrivID - CIC: 105 MSMC_mpf_error11 Memory protection fault indicators for each system master PrivID - CIC: 106 MSMC_mpf_error12 Memory protection fault indicators for each system master PrivID - CIC: 107 MSMC_mpf_error13 Memory protection fault indicators for each system master PrivID - CIC: 108 MSMC_mpf_error14 Memory protection fault indicators for each system master PrivID - CIC: 109 MSMC_mpf_error15 Memory protection fault indicators for each system master PrivID - CIC: 110 DDR3_ERR DDR3 ECC Error Interrupt - TCI6614, C6670: - CIC: 170 MSMC_mpf_error4 Memory protection fault indicators for each system master PrivID - CIC: 171 MSMC_mpf_error5 Memory protection fault indicators for each system master PrivID - CIC: 172 MSMC_mpf_error6 Memory protection fault indicators for each system master PrivID - CIC: 173 MSMC_mpf_error7 Memory protection fault indicators for each system master PrivID - */ - KeyStone_CIC_event_map(gpCIC_regs, 0 , gCIC_EXC_out_num); - KeyStone_CIC_event_map(gpCIC_regs, 2 , gCIC_EXC_out_num); - KeyStone_CIC_event_map(gpCIC_regs, 3 , gCIC_EXC_out_num); - KeyStone_CIC_event_map(gpCIC_regs, 4 , gCIC_EXC_out_num); - KeyStone_CIC_event_map(gpCIC_regs, 5 , gCIC_EXC_out_num); - KeyStone_CIC_event_map(gpCIC_regs, 16, gCIC_EXC_out_num); - KeyStone_CIC_event_map(gpCIC_regs, 18, gCIC_EXC_out_num); - KeyStone_CIC_event_map(gpCIC_regs, 19, gCIC_EXC_out_num); - KeyStone_CIC_event_map(gpCIC_regs, 20, gCIC_EXC_out_num); - KeyStone_CIC_event_map(gpCIC_regs, 21, gCIC_EXC_out_num); - gCIC_EXC_EN_MASK[0] |= - (1<<0 ) - |(1<<2 ) - |(1<<3 ) - |(1<<4 ) - |(1<<5 ) - |(1<<16) - |(1<<18) - |(1<<19) - |(1<<20) - |(1<<21); - - KeyStone_CIC_event_map(gpCIC_regs, 32, gCIC_EXC_out_num); - KeyStone_CIC_event_map(gpCIC_regs, 34, gCIC_EXC_out_num); - KeyStone_CIC_event_map(gpCIC_regs, 35, gCIC_EXC_out_num); - gCIC_EXC_EN_MASK[1] |= - (1<<(32-32)) - |(1<<(34-32)) - |(1<<(35-32)); - - KeyStone_CIC_event_map(gpCIC_regs, 99, gCIC_EXC_out_num); - KeyStone_CIC_event_map(gpCIC_regs, 100, gCIC_EXC_out_num); - KeyStone_CIC_event_map(gpCIC_regs, 102, gCIC_EXC_out_num); - KeyStone_CIC_event_map(gpCIC_regs, 103, gCIC_EXC_out_num); - KeyStone_CIC_event_map(gpCIC_regs, 104, gCIC_EXC_out_num); - KeyStone_CIC_event_map(gpCIC_regs, 105, gCIC_EXC_out_num); - KeyStone_CIC_event_map(gpCIC_regs, 106, gCIC_EXC_out_num); - KeyStone_CIC_event_map(gpCIC_regs, 107, gCIC_EXC_out_num); - KeyStone_CIC_event_map(gpCIC_regs, 108, gCIC_EXC_out_num); - KeyStone_CIC_event_map(gpCIC_regs, 109, gCIC_EXC_out_num); - KeyStone_CIC_event_map(gpCIC_regs, 110, gCIC_EXC_out_num); - gCIC_EXC_EN_MASK[3] |= - (1<<(99 -32*3)) - |(1<<(100-32*3)) - |(1<<(102-32*3)) - |(1<<(103-32*3)) - |(1<<(104-32*3)) - |(1<<(105-32*3)) - |(1<<(106-32*3)) - |(1<<(107-32*3)) - |(1<<(108-32*3)) - |(1<<(109-32*3)) - |(1<<(110-32*3)); - - if(C6670_EVM==DSP_Board_Type - ||DUAL_NYQUIST_EVM==DSP_Board_Type - ||TCI6614_EVM==DSP_Board_Type) - { - KeyStone_CIC_event_map(gpCIC_regs, 170, gCIC_EXC_out_num); - KeyStone_CIC_event_map(gpCIC_regs, 171, gCIC_EXC_out_num); - KeyStone_CIC_event_map(gpCIC_regs, 172, gCIC_EXC_out_num); - KeyStone_CIC_event_map(gpCIC_regs, 173, gCIC_EXC_out_num); - gCIC_EXC_EN_MASK[5] |= - (1<<(170-32*5)) - |(1<<(171-32*5)) - |(1<<(172-32*5)) - |(1<<(173-32*5)); - } - - /* ----------- Mapping MPU interrupt for different chips start -----------------------*/ - if(C6670_EVM==DSP_Board_Type - ||DUAL_NYQUIST_EVM==DSP_Board_Type - ||C6678_EVM==DSP_Board_Type) - { - /* route the following system events to CIC out - CIC: 90 MPU0 addressing violation interrupt and protection violation interrupt - CIC: 92 MPU1 addressing violation interrupt and protection violation interrupt - CIC: 94 MPU2 addressing violation interrupt and protection violation interrupt - CIC: 96 MPU3 addressing violation interrupt and protection violation interrupt - */ - KeyStone_CIC_event_map(gpCIC_regs, 90, gCIC_EXC_out_num); - KeyStone_CIC_event_map(gpCIC_regs, 92, gCIC_EXC_out_num); - KeyStone_CIC_event_map(gpCIC_regs, 94, gCIC_EXC_out_num); - KeyStone_CIC_event_map(gpCIC_regs, 96, gCIC_EXC_out_num); - gCIC_EXC_EN_MASK[2] |= - (1<<(90 -32*2)) - |(1<<(92 -32*2)) - |(1<<(94 -32*2)); - gCIC_EXC_EN_MASK[3] |= - (1<<(96 -32*3)); - - /* 6618_6670 only */ - if(C6670_EVM==DSP_Board_Type - ||DUAL_NYQUIST_EVM==DSP_Board_Type) - { - /* - CIC: 174 MPU4 addressing violation interrupt and protection violation interrupt - CIC: 180 MPU5 addressing violation interrupt and protection violation interrupt - */ - KeyStone_CIC_event_map(gpCIC_regs, 174, gCIC_EXC_out_num); - KeyStone_CIC_event_map(gpCIC_regs, 180, gCIC_EXC_out_num); - gCIC_EXC_EN_MASK[5] |= - (1<<(174-32*5)) - |(1<<(180-32*5)); - } - } - - if(TCI6614_EVM==DSP_Board_Type) - { - /* route the following system events to CIC out - CIC: 23 MPU0~7 addressing violation interrupt combine output - CIC: 37 MPU0~7 protection violation interrupt combine output - */ - KeyStone_CIC_event_map(gpCIC_regs, 23, gCIC_EXC_out_num); - KeyStone_CIC_event_map(gpCIC_regs, 37, gCIC_EXC_out_num); - gCIC_EXC_EN_MASK[0] |= - (1<<23); - gCIC_EXC_EN_MASK[1] |= - (1<<(37 -32)); - - } - /* ----------- Mapping MPU interrupt for different chips end -----------------------*/ - - /* Enable Global host interrupts. */ - gpCIC_regs->GLOBAL_ENABLE_HINT_REG= 1; - -} -/***************************************************************************** - Prototype : KeyStone_Exception_cfg - Description : Config the system err and external exception to generate the NMI. - Call this function as last step after all - configuration/initialization complete - Input : Bool bGlobalExceptionMaster. If TRUE, the global exception events - from CIC will be routed to exception model of this CPU core. - Output : None - Return Value : -*****************************************************************************/ -void KeyStone_Exception_cfg(Bool bGlobalExceptionMaster) -{ - - puts("Enable Exception handling..."); - - TSCL = 0; /* Enable the TSC */ - - memset(&exception_record, 0, sizeof(exception_record)); -#if 0 - /*Clear all CPU events*/ - gpCGEM_regs->EVTCLR[0]= 0xFFFFFFFF; - gpCGEM_regs->EVTCLR[1]= 0xFFFFFFFF; - gpCGEM_regs->EVTCLR[2]= 0xFFFFFFFF; - gpCGEM_regs->EVTCLR[3]= 0xFFFFFFFF; -#endif - /*clear memory fault*/ - gpCGEM_regs->L1PMPFCR = 1; - gpCGEM_regs->L1DMPFCR = 1; - gpCGEM_regs->L2MPFCR = 1; - gpXMC_regs->XMPFCR = 1; - - /*clear configuration bus error*/ - gpCGEM_regs->ICFGMPFCR= 1; - gpCGEM_regs->ECFGERRCLR= 1; - - /* clear the MDMAERR */ - gpCGEM_regs->MDMAERRCLR = 1; - - /*clear interrupt drop staus*/ - gpCGEM_regs->INTXCLR = 1; - - gpCGEM_regs->INTDMASK= ~IER; /*only monitor drop of enabled interrupts*/ - - /*enable events: - 10 MSMC_mpf_error_n MSMC Memory protection fault caused by local CorePac - 96 INTERR Dropped CPU interrupt event - 97 EMC_IDMAERR Invalid IDMA parameters - 110 MDMAERREVT XMC VBUSM error event - 113 PMC_ED Single bit error detected during DMA accesses L1P - 117 UMC_ED2 Uncorrected bit error detected LL2 - 119 SYS_CMPA CPU Memory Protection Fault for local configuration of INTC and power control - 120 PMC_CMPA CPU memory protection fault for L1P - 121 PMC_DMPA DMA memory protection fault for L1P - 122 DMC_CMPA CPU memory protection fault for L1D (and other memory read finally goes through the L1D controller) - 123 DMC_DMPA DMA memory protection fault for L1D - 124 UMC_CMPA CPU memory protection fault for LL2 - 125 UMC_DMPA DMA memory protection fault for LL2 - 126 EMC_CMPA CPU memory protection fault for other local configuration space between 0x01000000 - 0x01BFFFFF - 127 EMC_BUSERR Bus Error Interrupt for global configuration space between 0x01C00000 - 0x07FFFFFF - */ - gpCGEM_regs->EXPMASK[0]= ~(1<EXPMASK[1]= 0xFFFFFFFF; - gpCGEM_regs->EXPMASK[2]= 0xFFFFFFFF; - gpCGEM_regs->EXPMASK[3]= ~((1<<(CSL_GEM_INTERR - 96))| - (1<<(CSL_GEM_EMC_IDMAERR-96))| - (1<<(CSL_GEM_MDMAERREVT-96))| - (1<<(CSL_GEM_PMC_ED-96))| - (1<<(CSL_GEM_UMC_ED2-96))| - (1<<(CSL_GEM_SYS_CMPA-96))| - (1<<(CSL_GEM_PMC_CMPA-96))| - (1<<(CSL_GEM_PMC_DMPA-96))| - (1<<(CSL_GEM_DMC_CMPA-96))| - (1<<(CSL_GEM_DMC_DMPA-96))| - (1<<(CSL_GEM_UMC_CMPA-96))| - (1<<(CSL_GEM_UMC_DMPA-96))| - (1<<(CSL_GEM_EMC_CMPA-96))| - (1<<(CSL_GEM_EMC_BUSERR-96))); - - - if(bGlobalExceptionMaster) - { - /*enable exception events routed from CIC, - please note, this should be only configured for one CPU*/ - KeyStone_CIC_exception_events_mapping(); - gpCGEM_regs->EXPMASK[guwIntcCICExcEvtIdx>>5] &= (~(1<<(guwIntcCICExcEvtIdx&0x1F))); - } - - /*clear exception flag*/ - ECR = EFR; - IERR = 0; - - /*Eanble external exception, global exception enable*/ - TSR = TSR| - (1<>CSL_CGEM_MDMAERR_ERR_SHIFT; - if (1==err) { - puts(" MDMA read status error detected"); - } - else if (2==err) { - puts(" MDMA write status error detected"); - } - else if (3==err) { - puts(" CFG read status error detected"); - } - else if (4==err) { - puts(" CFG write status error detected"); - } - - printf(" XID (Transaction ID)= %d\n", - (ERR_REG & CSL_CGEM_MDMAERR_XID_MASK)>>CSL_CGEM_MDMAERR_XID_SHIFT); - - stat= (ERR_REG & CSL_CGEM_MDMAERR_STAT_MASK)>>CSL_CGEM_MDMAERR_STAT_SHIFT; - printf(" %s\n", bus_err_stat_str[stat]); -} - -/***************************************************************************** - Prototype : KeyStone_CIC_EXC_handler - Description : This function handle the exception events from CIC - Input : void - Output : None - Return Value : void - - History : - 1.Date : 2012/10/18 - Author : Zhan - Modification : Created function - - 2.Date : 2012/10/28 - Author : Brighton Feng - Modification : Add EDMA error processing - -*****************************************************************************/ -void KeyStone_CIC_EXC_handler() -{ - int i; - Uint32 status[4], status5 = 0; - - TDSP_Board_Type DSP_Board_Type; - - DSP_Board_Type= KeyStone_Get_dsp_board_type(); - - /*Step1: Disable CIC host interrupt*/ - KeyStone_CIC_disable_host_int(gpCIC_regs, gCIC_EXC_out_num); - - status[0]= gpCIC_regs->ENA_STATUS_REG[0]&gCIC_EXC_EN_MASK[0]; - status[1]= gpCIC_regs->ENA_STATUS_REG[1]&gCIC_EXC_EN_MASK[1]; - status[2]= gpCIC_regs->ENA_STATUS_REG[2]&gCIC_EXC_EN_MASK[2]; - status[3]= gpCIC_regs->ENA_STATUS_REG[3]&gCIC_EXC_EN_MASK[3]; - exception_record.status.ext_sts.CIC_STATUS[0]= status[0]; - exception_record.status.ext_sts.CIC_STATUS[1]= status[1]; - exception_record.status.ext_sts.CIC_STATUS[2]= status[2]; - exception_record.status.ext_sts.CIC_STATUS[3]= status[3]; - - /*Step2: clear system events*/ - gpCIC_regs->ENA_STATUS_REG[0]= status[0]; - gpCIC_regs->ENA_STATUS_REG[1]= status[1]; - gpCIC_regs->ENA_STATUS_REG[2]= status[2]; - gpCIC_regs->ENA_STATUS_REG[3]= status[3]; - - /* The different device INTC number is different, if read the non-exist space will - trigger the L1D memory protection error. - */ - if((C6670_EVM == DSP_Board_Type) - ||(DUAL_NYQUIST_EVM == DSP_Board_Type) - ||(TCI6614_EVM == DSP_Board_Type)) - { - status5 = gpCIC_regs->ENA_STATUS_REG[5]&gCIC_EXC_EN_MASK[5]; - exception_record.status.ext_sts.CIC_STATUS[5]= status5; - - /*Step2: clear system events*/ - gpCIC_regs->ENA_STATUS_REG[5]= status5 ; - } - - /*----------------------------EDMA error-----------------------------*/ - /* - CIC: 0 EDMA3CC1 EDMACC_ERRINT EDMA3CC1 error interrupt - CIC: 2 EDMA3CC1 EDMATC_ERRINT0 EDMA3CC1 EDMA3TC0 error interrupt - CIC: 3 EDMA3CC1 EDMATC_ERRINT1 EDMA3CC1 EDMA3TC1 error interrupt - CIC: 4 EDMA3CC1 EDMATC_ERRINT2 EDMA3CC1 EDMA3TC2 error interrupt - CIC: 5 EDMA3CC1 EDMATC_ERRINT3 EDMA3CC1 EDMA3TC3 error interrupt*/ - if(status[0]&0x3D) - EDMA_error_handler(1, status[0]&0x3D); - - /* - CIC: 16 EDMA3CC2 EDMACC_ERRINT EDMA3CC2 error interrupt - CIC: 18 EDMA3CC2 EDMATC_ERRINT0 EDMA3CC2 EDMA3TC0 error interrupt - CIC: 19 EDMA3CC2 EDMATC_ERRINT1 EDMA3CC2 EDMA3TC1 error interrupt - CIC: 20 EDMA3CC2 EDMATC_ERRINT2 EDMA3CC2 EDMA3TC2 error interrupt - CIC: 21 EDMA3CC2 EDMATC_ERRINT3 EDMA3CC2 EDMA3TC3 error interrupt*/ - if((status[0]>>16)&0x3D) - EDMA_error_handler(2, (status[0]>>16)&0x3D); - - /* - CIC: 32 EDMA3CC0 EDMACC_ERRINT EDMA3CC0 error interrupt - CIC: 34 EDMA3CC0 EDMATC_ERRINT0 EDMA3CC0 EDMA3TC0 error interrupt - CIC: 35 EDMA3CC0 EDMATC_ERRINT1 EDMA3CC0 EDMA3TC1 error interrupt*/ - if(status[1]&0xD) - EDMA_error_handler(0, status[1]&0xD); - - /*----------------------------MPU error-----------------------------*/ - if(TCI6614_EVM == DSP_Board_Type) - { - //CIC: 23 MPU0~7 addressing violation interrupt combine output - //CIC: 37 MPU0~7 protection violation interrupt combine output - if((status[0]&(1<<23))||(status[1]&(1<<(37-32)))) - { - for(i=0; i<8; i++) - { - /*MPU5 (for BCP) of TCI6614 is only accessible - when BCP is enabled through PSC*/ - if((5==i)&& - ((CSL_PSC_getPowerDomainState(5) != PSC_PDSTATE_ON) || - (CSL_PSC_getModuleState (12) != PSC_MODSTATE_ENABLE))) - continue; - - if(gpMPU_regs[i]->INT_RAW_STATUS_SET & 0x3) - { - KeyStone_peripherals_MPU_excepiton_handler(i); - } - } - - /*The MPU events in TCI6614 are different from other KeyStone - devices. All the MPU0~7 events are combined into single event - and connected to the CIC0 as one system event. - We have to clear the MPU event flag at the source level first - and then are able to clear the CIC flags because the INTD for the - MPU events is for the combination purpose but do not convert - the level interrupt to pulse.*/ - /*clear system events*/ - gpCIC_regs->ENA_STATUS_REG[0]= status[0]; - gpCIC_regs->ENA_STATUS_REG[1]= status[1]; - } - } - else - { - //CIC: 90 MPU0 addressing violation interrupt and protection violation interrupt - if(status[2]&(1<<(90-64))) - { - KeyStone_peripherals_MPU_excepiton_handler(0); - } - //CIC: 92 MPU1 addressing violation interrupt and protection violation interrupt - if(status[2]&(1<<(92-64))) - { - KeyStone_peripherals_MPU_excepiton_handler(1); - } - //CIC: 94 MPU2 addressing violation interrupt and protection violation interrupt - if(status[2]&(1<<(94-64))) - { - KeyStone_peripherals_MPU_excepiton_handler(2); - } - //CIC: 96 MPU3 addressing violation interrupt and protection violation interrupt - if(status[3]&(1<<(96-96))) - { - KeyStone_peripherals_MPU_excepiton_handler(3); - } - - if((C6670_EVM == DSP_Board_Type) - ||(DUAL_NYQUIST_EVM == DSP_Board_Type)) - { - //CIC: 174 MPU4 addressing violation interrupt and protection violation interrupt - //CIC: 180 MPU5 addressing violation interrupt and protection violation interrupt - if(status5&(1<<(174-160))) - { - KeyStone_peripherals_MPU_excepiton_handler(4); - } - if(status5&(1<<(180-160))) - { - KeyStone_peripherals_MPU_excepiton_handler(5); - } - } - } - - /*----------------------------MSMC error-----------------------------*/ - //CIC: 99 MSMC_dedc_nc_error Non-correctable (2-bit) soft error detected on SRAM read - if(status[3]&(1<<(99-96))) - { - KeyStone_SL2_EDC_handler(); - } - //CIC: 100 MSMC_scrub_nc_error Non-correctable (2-bit) soft error detected during scrub cycle - if(status[3]&(1<<(100-96))) - { - KeyStone_SL2_EDC_handler(); - } - - /* - CIC: 102 MSMC_mpf_error8 Memory protection fault indicators for each system master PrivID - CIC: 103 MSMC_mpf_error9 Memory protection fault indicators for each system master PrivID - CIC: 104 MSMC_mpf_error10 Memory protection fault indicators for each system master PrivID - CIC: 105 MSMC_mpf_error11 Memory protection fault indicators for each system master PrivID - CIC: 106 MSMC_mpf_error12 Memory protection fault indicators for each system master PrivID - CIC: 107 MSMC_mpf_error13 Memory protection fault indicators for each system master PrivID - CIC: 108 MSMC_mpf_error14 Memory protection fault indicators for each system master PrivID - CIC: 109 MSMC_mpf_error15 Memory protection fault indicators for each system master PrivID*/ - if((status[3]>>(102-96))&0xFF) - KeyStone_MSMC_protection_exception_handler(); - - if((C6670_EVM == DSP_Board_Type) - ||(DUAL_NYQUIST_EVM == DSP_Board_Type) - ||(TCI6614_EVM == DSP_Board_Type)) - { - /* - CIC: 170 MSMC_mpf_error4 Memory protection fault indicators for each system master PrivID - CIC: 171 MSMC_mpf_error5 Memory protection fault indicators for each system master PrivID - CIC: 172 MSMC_mpf_error6 Memory protection fault indicators for each system master PrivID - CIC: 173 MSMC_mpf_error7 Memory protection fault indicators for each system master PrivID*/ - if((status5>>(170-160))&0xF) - KeyStone_MSMC_protection_exception_handler(); - - } - - /*----------------------------DDR ECC error-------------------------*/ - //CIC: 110 DDR3_ERR DDR3_EMIF Error Interrupt - if(status[3]&(1<<(110-96))) - { - printf(" DDR ECC error happened during "); - - exception_record.status.ext_sts.info.memory.fault_status.DDR_IRQSTATUS_SYS= - gpDDR_regs->IRQSTATUS_SYS; - - if(gpDDR_regs->IRQSTATUS_SYS&CSL_EMIF4F_IRQSTATUS_SYS_REG_RD_ECC_ERR_SYS_MASK) - printf("read "); - if(gpDDR_regs->IRQSTATUS_SYS&CSL_EMIF4F_IRQSTATUS_SYS_REG_WR_ECC_ERR_SYS_MASK) - printf("write "); - printf(".\n"); - - //clear the status - gpDDR_regs->IRQSTATUS_SYS= CSL_EMIF4F_IRQSTATUS_SYS_REG_RD_ECC_ERR_SYS_MASK - |CSL_EMIF4F_IRQSTATUS_SYS_REG_WR_ECC_ERR_SYS_MASK; - } - - /*Step3: Enable the CIC host interrupt */ - KeyStone_CIC_enable_host_int(gpCIC_regs, gCIC_EXC_out_num); - -} - -/***************************************************************************** - Prototype : KeyStone_EXC_external - Description : external exception processing - Input : void - Output : None - Return Value : - - History : - 1.Date : 2010/12/12 - Author : Brighton Feng - Modification : Created function -*****************************************************************************/ -void KeyStone_EXC_external(void) -{ - int i; - unsigned int INTXSTAT, flag[4]; - - for(i= 0; i<4; i++) - { - flag[i] = gpCGEM_regs->MEXPFLAG[i]; - if(flag[i]) - { - exception_record.status.ext_sts.MEXPFLAG[i]= flag[i]; - printf("External exception happened. MEXPFLAG[%d]=0x%x.\n", - i, flag[i]); - gpCGEM_regs->EVTCLR[i] = flag[i]; - } - } - - if(0 == (flag[0]|flag[1]|flag[2]|flag[3])) - { - puts("Enter external Exception service routine, but external excpetion flage is 0!"); - return; - } - - /*Exception events routed from CIC*/ - if(flag[guwIntcCICExcEvtIdx>>5] & (1<<(guwIntcCICExcEvtIdx&0x1F))) - { - KeyStone_CIC_EXC_handler(); - } - - /*MSMC memory protection exception*/ - if(flag[0]&(1<INTXSTAT; - exception_record.status.ext_sts.info.INTXSTAT= INTXSTAT; - - if(INTXSTAT&CSL_CGEM_INTXSTAT_DROP_MASK) - printf(" Event 96: DSP Interrupt %d (INTC input Event %d) dropped\n", - (INTXSTAT&CSL_CGEM_INTXSTAT_CPUINT_MASK)>>CSL_CGEM_INTXSTAT_CPUINT_SHIFT, - (INTXSTAT&CSL_CGEM_INTXSTAT_SYSINT_MASK)>>CSL_CGEM_INTXSTAT_SYSINT_SHIFT); - } - - if(flag[3]&(1<<(CSL_GEM_EMC_IDMAERR-96))) - puts(" Event 97: EMC_IDMAERR Invalid IDMA parameters"); - - /*MDMA XMC VBUSM error*/ - if(flag[3]&(1<<(CSL_GEM_MDMAERREVT-96))) - { - puts(" Event 110: MDMAERREVT XMC VBUSM error event"); - if(gpXMC_regs->XMPFSR) - { - /*XMC protection error*/ - memory_protection_exception_handler(gpXMC_regs->XMPFAR, gpXMC_regs->XMPFSR); - gpXMC_regs->XMPFCR = 1; - } - else - { - /*other VBUSM error*/ - Bus_error_handler(gpCGEM_regs->MDMAERR); - } - /* clear the MDMAERR */ - gpCGEM_regs->MDMAERRCLR = 1; - } - - /*L1P Single bit error detected during DMA read*/ - if(flag[3]&(1<<(CSL_GEM_PMC_ED-96))) - { - puts(" Event 113: PMC_ED Single bit error detected during DMA read"); - L1P_ED_handler(); - } - - /*LL2 Uncorrected bit error detected*/ - if(flag[3]&(1<<(CSL_GEM_UMC_ED2-96))) - { - puts(" Event 117: UMC_ED2 Uncorrected bit error detected"); - LL2_EDC_handler(FALSE); - } - - /*local register memory protection exception*/ - if(flag[3]&(1<<(CSL_GEM_SYS_CMPA-96))) - { - puts(" Event 119: SYS_CMPA CPU Memory Protection Fault for local configuration of INTC and power control"); - } - - /*L1P memory protection exception*/ - if(flag[3]&(3<<(CSL_GEM_PMC_CMPA-96))) - { - if(flag[3]&(1<<(CSL_GEM_PMC_CMPA-96))) - puts(" Event 120: PMC_CMPA CPU memory protection fault for L1P"); - if(flag[3]&(1<<(CSL_GEM_PMC_DMPA-96))) - puts(" Event 121: PMC_DMPA DMA memory protection fault for L1P"); - memory_protection_exception_handler(gpCGEM_regs->L1PMPFAR, gpCGEM_regs->L1PMPFSR); - gpCGEM_regs->L1PMPFCR = 1; - } - - /*L1D memory protection exception*/ - if(flag[3]&(3<<(CSL_GEM_DMC_CMPA-96))) - { - if(flag[3]&(1<<(CSL_GEM_DMC_CMPA-96))) - puts(" Event 122: DMC_CMPA CPU memory protection fault for L1D (and other memory read finally goes through the L1D controller)"); - if(flag[3]&(1<<(CSL_GEM_DMC_DMPA-96))) - puts(" Event 123: DMC_DMPA DMA memory protection fault for L1D"); - memory_protection_exception_handler(gpCGEM_regs->L1DMPFAR, gpCGEM_regs->L1DMPFSR); - gpCGEM_regs->L1DMPFCR = 1; - } - - /*LL2 memory protection exception*/ - if(flag[3]&(3<<(CSL_GEM_UMC_CMPA-96))) - { - if(flag[3]&(1<<(CSL_GEM_UMC_CMPA-96))) - puts(" Event 124: UMC_CMPA CPU memory protection fault for L2 "); - if(flag[3]&(1<<(CSL_GEM_UMC_DMPA-96))) - puts(" Event 125: UMC_DMPA DMA memory protection fault for L2 "); - memory_protection_exception_handler(gpCGEM_regs->L2MPFAR, gpCGEM_regs->L2MPFSR); - gpCGEM_regs->L2MPFCR = 1; - } - - /*local registers protection exception*/ - if(flag[3]&(1<<(CSL_GEM_EMC_CMPA-96))) - { - puts(" Event 126: EMC_CMPA CPU memory protection fault for local configuration space between 0x01000000-0x01BFFFFF"); - memory_protection_exception_handler(gpCGEM_regs->ICFGMPFAR, gpCGEM_regs->ICFGMPFSR); - gpCGEM_regs->ICFGMPFCR= 1; - } - - /*external configuration bus error*/ - if(flag[3]&(Uint32)(1<<(CSL_GEM_EMC_BUSERR-96))) - { - puts(" Event 127: EMC_BUSERR Bus Error Interrupt for global configuration space between 0x01C00000 - 0x07FFFFFF"); - Bus_error_handler(gpCGEM_regs->ECFGERR); - gpCGEM_regs->ECFGERRCLR= 1; - } -} - -char * internal_exception_str[]= -{ - "Instruction fetch exception", - "Fetch packet exception", - "Execute packet exception", - "Opcode exception", - "Resource conflict exception", - "Resource access exception", - "Privilege exception", - "SPLOOP buffer exception", - "Missed stall exception" -}; - -/***************************************************************************** - Prototype : EXC_internal - Description : internal exception handler - Input : void - Output : None - Return Value : - - History : - 1.Date : 2010/12/12 - Author : Brighton Feng - Modification : Created function - -*****************************************************************************/ -/*internal exception handler*/ -void EXC_internal(void) -{ - int i; - unsigned int ierr; - - /*record IERR */ - ierr = IERR; - exception_record.status.IERR= ierr; - - if(ierr) - { - /*Clear internal excpeiton flag*/ - IERR= 0; - - printf("internal excpetion happened. IERR=0x%x.\n", ierr); - for(i=0; i<9; i++) - { - if((ierr>>i)&1) - printf(" %s\n", internal_exception_str[i]); - } - if (ierr & CSL_CHIP_IERR_IFX_MASK) { - /* L1P EDC Processing*/ - L1P_ED_handler(); - } - } - else - puts("Enter Internal Exception service routine, but internal excpetion flage is 0!"); - -} -/***************************************************************************** - Prototype : EXC_nmi - Description : NMI processing - Input : void - Output : None - Return Value : - - History : - 1.Date : 2010/12/12 - Author : Brighton Feng - Modification : Created function - -*****************************************************************************/ -void EXC_NMI(void) -{ - puts("NMI exception happened, normally you should reset the DSP to recover from the problem!"); -} - -/***************************************************************************** - Prototype : EXC_swgen - Description : software generated exception handler - Input : void - Output : None - Return Value : -*****************************************************************************/ -void EXC_swgen(void) -{ - puts("Software generated exception happened."); -} - -/***************************************************************************** - Prototype : Exception_service_routine - Description : Exception service routine - Input : void - Output : None - Return Value : - - History : - 1.Date : 2010/12/12 - Author : Brighton Feng - Modification : Created function - -*****************************************************************************/ -#pragma NMI_INTERRUPT( Exception_service_routine ); -void Exception_service_routine(void) -{ - unsigned int efr, nrp, ntsr, tscl, tsch, irp, itsr; - - /*record timestamp*/ - tscl = TSCL; - exception_record.TSCL= tscl; - tsch = TSCH; - exception_record.TSCH= tsch; - - nrp = NRP; /*record NRP */ - exception_record.NRP= nrp; - ntsr = NTSR; /*record NTSR */ - exception_record.NTSR= ntsr; - efr = EFR; /*record EFR */ - exception_record.EFR= efr; - - irp = IRP; /*record IRP */ - itsr = ITSR; /*record ITSR */ - exception_record.IRP= irp; - exception_record.ITSR= itsr; - - if(efr) - { - /*Clear excpeiton flag*/ - ECR = efr; - - /*check all possible exceptions*/ - if (efr & CSL_CHIP_EFR_OXF_MASK) { - /* S/W generated exception */ - EXC_swgen(); - } - if (efr & CSL_CHIP_EFR_IXF_MASK) { - /* internal exception */ - EXC_internal(); - } - if (efr & CSL_CHIP_EFR_EXF_MASK) { - /* external exception */ - KeyStone_EXC_external(); - } - if (efr & CSL_CHIP_EFR_NXF_MASK) { - /* legacy NMI exception */ - EXC_NMI(); - } - } - else - puts("Enter Exception service routine, but excpetion flage is 0!"); - - printf("NRP=0x%x, NTSR=0x%x, IRP=0x%x, ITSR=0x%x, TSCH= 0x%x, TSCL= 0x%x\n", - nrp, ntsr, irp, itsr, tsch, tscl); - - printf(" B3=0x%x, A4=0x%x, B4= 0x%x, B14= 0x%x, B15= 0x%x\n", - exception_record.B3, exception_record.A4, - exception_record.B4, exception_record.B14, - exception_record.B15); - - /* - It is not always possible to safely exit the exception handling routine. Conditions that - can prevent a safe return from exceptions include: - 1. SPLOOPs that are terminated by an exception cannot be resumed correctly. The - SPLX bit in NTSR should be verified to be 0 before returning. - 2. Exceptions that occur when interrupts are blocked cannot be resumed correctly. - The IB bit in NTSR should be verified to be 0 before returning. - 3. Exceptions that occur at any point in the code that cannot be interrupted safely - (for example, a tight loop containing multiple assignments) cannot be safely - returned to. The compiler will normally disable interrupts at these points in the - program; check the GIE bit in NTSR to be 1 to verify that this condition is met. - 4. NRP is not in valid address space*/ - if((ntsr&CSL_CHIP_TSR_SPLX_MASK) - ||(ntsr&CSL_CHIP_TSR_IB_MASK) - ||(0==(ntsr&CSL_CHIP_TSR_GIE_MASK)) - ||(0x800000>NRP)) - { - puts("Exception happened at a place can not safely return!"); - //while(1); //trap - exit(0); - } - -} - -/***************************************************************************** - Prototype : Nested_Exception_service_routine - Description : Nested Exception service routine - When a non-maskable exception happens in the first exception service routine, - then the reset vector is used when redirecting program execution to service the second - exception. In this case, NTSR and NRP are left unchanged. TSR is copied to ITSR and - the current PC is copied to IRP. TSR is set to the default exception processing value and - the NMIE bit in IER is cleared in this case preventing any further external exceptions. - Input : void - Output : None - Return Value : - - History : - 1.Date : 2010/12/29 - Author : Brighton Feng - Modification : Created function - -*****************************************************************************/ -interrupt void Nested_Exception_service_routine(void) -{ - unsigned int tscl, tsch; - - /*record timestamp*/ - tscl = TSCL; - tsch = TSCH; - - if(0==exception_record.TSCL) - exception_record.TSCL= tscl; - if(0==exception_record.TSCH) - exception_record.TSCH= tsch; - if(0==exception_record.NRP) - exception_record.NRP= NRP; - if(0==exception_record.NTSR) - exception_record.NTSR= NTSR; - if(0==exception_record.EFR) - exception_record.EFR= EFR; - if(0==exception_record.status.IERR) - exception_record.status.IERR= IERR; - - exception_record.IRP= IRP; - exception_record.ITSR= ITSR; - - printf("Nested exception happened! IRP=0x%x, ITSR=0x%x\n", - IRP, ITSR); - - printf("NRP=0x%x, NTSR=0x%x, EFR=0x%x, IERR=0x%x, TSCH= 0x%x, TSCL= 0x%x\n", - NRP, NTSR, EFR, IERR, tsch, tscl); - - while(1); //trap -// exit(0); -} - -/*=========================other utility functions==========================*/ -/*clear all interrupt flag/status, setup ISTP to begining of LL2*/ -void CPU_interrupt_init() -{ - //clear interrupt and excpetion events - ICR = IFR; - ECR = EFR; - IER= 3; //disable all interrupts - - /* disable event combine */ - gpCGEM_regs->EVTMASK[0] = 0xffffffff; - gpCGEM_regs->EVTMASK[1] = 0xffffffff; - gpCGEM_regs->EVTMASK[2] = 0xffffffff; - gpCGEM_regs->EVTMASK[3] = 0xffffffff; - - /*Clear all CPU events*/ - gpCGEM_regs->EVTCLR[0]= 0xFFFFFFFF; - gpCGEM_regs->EVTCLR[1]= 0xFFFFFFFF; - gpCGEM_regs->EVTCLR[2]= 0xFFFFFFFF; - gpCGEM_regs->EVTCLR[3]= 0xFFFFFFFF; - - /*Interrupt Service Table Pointer to begining of LL2 memory*/ - ISTP= 0x800000; -} - -/*enable interrupt to CPU: IER |= uiIER_en_mask; GIE=1*/ -void CPU_interrupt_enable(Uint32 uiIER_en_mask) -{ - ICR= uiIER_en_mask; - IER |= uiIER_en_mask; - - //enable GIE - TSR = TSR|1; -} - -/***************************************************************************** - Prototype : KeyStone_get_device_info - Description : Get device information - Input : None - Output : None - Return Value : - - History : - 1.Date : 2010/12/12 - Author : Brighton Feng - Modification : Created function - 2.Date : 2014/12/2 - Author : Brighton Feng - Modification : Update to parser device type, boot mode, endian information, - speed grade, required CVDD - -*****************************************************************************/ -//get device speed grade from the EFUSE register -void KeyStone_get_device_speed_grade() -{ - Uint32 uiDevSpeed, uiSpeedCode; - - uiSpeedCode= (DEVSPEED&DEVSPEED_DSP_SPEED_MASK)>>DEVSPEED_DSP_SPEED_SHIFT; - - if(uiSpeedCode&DEVSPEED_800_MHZ_MASK_H) uiDevSpeed= 800; - else if(uiSpeedCode&DEVSPEED_1000_MHZ_MASK_H) uiDevSpeed= 1000; - else if(uiSpeedCode&DEVSPEED_1200_MHZ_MASK_H) uiDevSpeed= 1200; - else if(uiSpeedCode&DEVSPEED_1250_MHZ_MASK_H) uiDevSpeed= 1250; - else if(uiSpeedCode&DEVSPEED_1400_MHZ_MASK_H) uiDevSpeed= 1400; - else if(uiSpeedCode&DEVSPEED_1400_MHZ_MASK_L) uiDevSpeed= 1400; - else if(uiSpeedCode&DEVSPEED_1250_MHZ_MASK_L) uiDevSpeed= 1250; - else if(uiSpeedCode&DEVSPEED_1200_MHZ_MASK_L) uiDevSpeed= 1200; - else if(uiSpeedCode&DEVSPEED_1000_MHZ_MASK_L) uiDevSpeed= 1000; - else uiDevSpeed= 800; - - printf("Device speed grade = %dMHz.\n", uiDevSpeed); -} - -char * device_type_str[]= -{ - "TCI6616", - "C6670/TCI6618", - "C6678/TCI6608", - "TCI6614", - "unknown" -}; -char * endian_str[]= -{ - "big", - "little" -}; -char * boot_mode_str[]= -{ - "No boot or EMIF16(NOR FLASH) or UART", - "Serial Rapid I/O", - "Ethernet (SGMII)", - "Ethernet (SGMII) or NAND FLASH", - "PCIE", - "I2C", - "SPI", - "HyperLink" - }; -char * input_clk_str[]= -{ - "50MHz", - "66.67MHz", - "80MHz", - "100MHz", - "156.25MHz", - "250MHz", - "312.5MHz", - "122.88MHz", - "bypassed" -}; -void KeyStone_get_device_info() -{ - char * boot_mode; - Uint8 ucBootMode, ucBootMaster; - Uint32 uiVID; - Uint8 ucPLL_cfg= 8; //8 means bypassed - Uint32 * DieID= (Uint32 *)&gpBootCfgRegs->DIE_ID_REG0; - Uint32 uiJTAG_ID = gpBootCfgRegs->DEVICE_ID_REG0; - Uint32 uiDevStat = gpBootCfgRegs->BOOT_REG0; - - gDSP_board_type=KeyStone_Get_dsp_board_type(); - - ucBootMode= (uiDevStat&DEVSTAT_BOOTMODE_MASK)>>DEVSTAT_BOOTMODE_SHIFT; - ucBootMaster= (uiDevStat&DEVSTAT_BOOTMASTER_MASK)>>DEVSTAT_BOOTMASTER_SHIFT; - - if((TCI6614_EVM==gDSP_board_type)&&(1==ucBootMaster)) - { - boot_mode= "ARM"; //ARM boot - } - else - boot_mode= boot_mode_str[ucBootMode]; - - //PLL is not configured with SPI and I2C master boot mode - if((5!=ucBootMode)&&(6!=ucBootMode)) - ucPLL_cfg= (uiDevStat&DEVSTAT_SYSPLL_MASK)>>DEVSTAT_SYSPLL_SHIFT; - - printf("JTAG ID= 0x%08x. This is %s device, version variant = %d.\n", uiJTAG_ID, - device_type_str[gDSP_board_type], uiJTAG_ID>>28); - - printf("DEVSTAT= 0x%08x. %s endian, %s boot, PLL configuration implies the input clock for core is %s.\n", - uiDevStat, endian_str[uiDevStat&DEVSTAT_LENDIAN_MASK], boot_mode, - input_clk_str[ucPLL_cfg]); - - uiVID= (gpPSC_regs->VCNTLID&CSL_PSC_VCNTLID_VCNTL_MASK)>>CSL_PSC_VCNTLID_VCNTL_SHIFT; - printf("SmartReflex VID= %d, required core voltage= %.3fV.\n", uiVID, 0.7+(float)uiVID*0.41/64.f); - - printf("Die ID= 0x%08x, 0x%08x, 0x%08x, 0x%08x\n", DieID[0], DieID[1], DieID[2], DieID[3]); - - KeyStone_get_device_speed_grade(); -} -/***************************************************************************** - Prototype : KeyStone_common_device_init - Description : common initialization for internal modules in K2 device - enable memory protection interrupts, EDC for MSMC RAM - History : - 1.Date : July 11, 2014 - Author : Brighton Feng - Modification : Created function -*****************************************************************************/ -void KeyStone_common_device_init() -{ - int i; - KeyStone_get_device_info(); - - /* enable common MPU interrupts */ - for(i=0; i<4; i++) - { - KeyStone_MPU_interrupt_enable(i); - } - - /*Enable MSMC EDC and setup scrubbing cycle counter= 255*1024*/ - KeyStone_SL2_EDC_enable(255); -} - -/***************************************************************************** - Prototype : KeyStone_common_CPU_init - Description : common initialization for internal modules in K2 device - enable TSC, EDC for local RAM; clear cache; protect L1 as cache - History : - 1.Date : September 1, 2014 - Author : Brighton Feng - Modification : Created function -*****************************************************************************/ -void KeyStone_common_CPU_init() -{ - TSC_init(); //initialize TSC to measure cycle - - /*clear all interrupt flag/status, setup ISTP to begining of LL2*/ - CPU_interrupt_init(); - - /*clean cache from previous run, not required from power on or cold reset*/ - CACHE_wbInvAllL2(CACHE_WAIT); - CSL_XMC_invalidatePrefetchBuffer(); - _mfence(); - _mfence(); - - /* protect L1 as cache */ - L1_cache_protection(); - - //Enable MSMC Memory protection error interrupt for local core, refer to MSMC user guide section3.8 - KeyStone_MSMC_MP_interrupt_en(1< -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/*----------------------PLL registers definition----------------*/ -#define PLLCTL0_PLLD_SHIFT (0) -#define PLLCTL0_PLLD_MASK (0x3F<>4) | 0x80000000) - -/*max number in two numbers*/ -#define MAX(a, b) (a>b?a:b) -/*min number in two numbers*/ -#define MIN(a, b) (a0xFFFF*4) - byteCnt= 0xFFFF*4; - if((Uint32)blockPtr>=0x0C000000&&(Uint32)blockPtr<0x0D000000) //SL2 - { - CACHE_invL1d((void *)blockPtr, byteCnt, CACHE_WAIT); - CSL_XMC_invalidatePrefetchBuffer(); - } - else if((Uint32)blockPtr>=0x10000000) //DDR or other cores - { - CACHE_invL2((void *)blockPtr, byteCnt, CACHE_WAIT); - CSL_XMC_invalidatePrefetchBuffer(); - } - _mfence(); - _mfence(); - -#if CACHE_DISABLE_INT -/*workaround for the "L2 Cache Corruption During Block and Global Coherence Operations -Issue" described in errata of some devices*/ - asm(" nop 8"); - asm(" nop 8"); - _restore_interrupts(uiOldGIE); //restore interrupt -#endif -} - -static inline void WritebackCache(void * blockPtr, Uint32 byteCnt) -{ - if(byteCnt>0xFFFF*4) - byteCnt= 0xFFFF*4; - if((Uint32)blockPtr>=0x0C000000&&(Uint32)blockPtr<0x0D000000) //SL2 - { - CACHE_wbL1d((void *)blockPtr, byteCnt, CACHE_WAIT); - } - else if((Uint32)blockPtr>=0x10000000) //DDR or other cores - { - CACHE_wbL2((void *)blockPtr, byteCnt, CACHE_WAIT); - } - _mfence(); - _mfence(); -} - -static inline void WritebackAllCache(void * blockPtr) -{ - if((Uint32)blockPtr>=0x0C000000&&(Uint32)blockPtr<0x0D000000) //SL2 - { - CACHE_wbAllL1d(CACHE_WAIT);; - } - else if((Uint32)blockPtr>=0x10000000) //DDR or other cores - { - CACHE_wbAllL2(CACHE_WAIT); - } - _mfence(); - _mfence(); -} - -static inline void WritebackInvalidCache(void * blockPtr, Uint32 byteCnt) -{ -#if CACHE_DISABLE_INT -/*workaround for the "L2 Cache Corruption During Block and Global Coherence Operations -Issue" described in errata of some devices*/ - Uint32 uiOldGIE= _disable_interrupts(); -#endif - - if(byteCnt>0xFFFF*4) - byteCnt= 0xFFFF*4; - if((Uint32)blockPtr>=0x0C000000&&(Uint32)blockPtr<0x0D000000) //SL2 - { - CACHE_wbInvL1d((void *)blockPtr, byteCnt, CACHE_WAIT); - CSL_XMC_invalidatePrefetchBuffer(); - } - else if((Uint32)blockPtr>=0x10000000) //DDR or other cores - { - CACHE_wbInvL2((void *)blockPtr, byteCnt, CACHE_WAIT); - CSL_XMC_invalidatePrefetchBuffer(); - } - _mfence(); - _mfence(); - -#if CACHE_DISABLE_INT -/*workaround for the "L2 Cache Corruption During Block and Global Coherence Operations -Issue" described in errata of some devices*/ - asm(" nop 8"); - asm(" nop 8"); - _restore_interrupts(uiOldGIE); //restore interrupt -#endif -} - -static inline void WritebackInvalidAllCache(void * blockPtr) -{ -#if CACHE_DISABLE_INT -/*workaround for the "L2 Cache Corruption During Block and Global Coherence Operations -Issue" described in errata of some devices*/ - Uint32 uiOldGIE= _disable_interrupts(); -#endif - - if((Uint32)blockPtr>=0x0C000000&&(Uint32)blockPtr<0x0D000000) //SL2 - { - CACHE_wbInvAllL1d(CACHE_WAIT);//CACHE_invL1d((void *)blockPtr, byteCnt, CACHE_WAIT); - CSL_XMC_invalidatePrefetchBuffer(); - } - else if((Uint32)blockPtr>=0x10000000) //DDR or other cores - { - //CACHE_invL2((void *)blockPtr, byteCnt, CACHE_WAIT); - CACHE_wbInvAllL2(CACHE_WAIT); - CSL_XMC_invalidatePrefetchBuffer(); - } - _mfence(); - _mfence(); - -#if CACHE_DISABLE_INT -/*workaround for the "L2 Cache Corruption During Block and Global Coherence Operations -Issue" described in errata of some devices*/ - asm(" nop 8"); - asm(" nop 8"); - _restore_interrupts(uiOldGIE); //restore interrupt -#endif -} - -static inline unsigned int SWAP_ENDIAN(unsigned int byte_index) -{ -#ifdef _BIG_ENDIAN - return ((byte_index&0xFFFFFFFC)+(3-byte_index&3)); -#else - return byte_index; -#endif -} - -static inline void KeyStone_CIC_clear_system_event(CSL_CPINTCRegs* cpIntcRegs, - int input_event_num) -{ - volatile Uint32 dummy_value; - - /*clear input interrupts events*/ - cpIntcRegs->STATUS_CLR_INDEX_REG= input_event_num; - - /*dummy read to make sure the previous write data land into the register*/ - dummy_value= cpIntcRegs->STATUS_CLR_INDEX_REG; -} - -static inline void KeyStone_CIC_disable_host_int(CSL_CPINTCRegs* cpIntcRegs, - int host_int_num) -{ - volatile Uint32 dummy_value; - - /* Disable the host interrupt */ - cpIntcRegs->HINT_ENABLE_CLR_INDEX_REG = host_int_num; - - /*dummy read to make sure the previous write data land into the register*/ - dummy_value= cpIntcRegs->HINT_ENABLE_CLR_INDEX_REG; -} - -static inline void KeyStone_CIC_enable_host_int(CSL_CPINTCRegs* cpIntcRegs, - int host_int_num) -{ - volatile Uint32 dummy_value; - - /* Enable the host interrupt */ - cpIntcRegs->HINT_ENABLE_SET_INDEX_REG = host_int_num; - - /*dummy read to make sure the previous write data land into the register*/ - dummy_value= cpIntcRegs->HINT_ENABLE_SET_INDEX_REG; -} - -static inline void KeyStone_CIC_event_map(CSL_CPINTCRegs* cpIntcRegs, - int input_event_num, int out_num) -{ - /*Map input event to output*/ - cpIntcRegs->CH_MAP[SWAP_ENDIAN(input_event_num)]= out_num; - - /*clear input interrupts events*/ - cpIntcRegs->STATUS_CLR_INDEX_REG= input_event_num; - - /*enable input interrupts events*/ - cpIntcRegs->ENABLE_SET_INDEX_REG= input_event_num; - - /*enable output*/ - cpIntcRegs->HINT_ENABLE_SET_INDEX_REG= out_num; -} - - -typedef enum -{ - DUAL_NYQUIST_EVM = 0, - C6670_EVM, - C6678_EVM, - TCI6614_EVM, - C6657_EVM, - UNKNOWN -}TDSP_Board_Type; - -extern TDSP_Board_Type gDSP_board_type; - -static inline TDSP_Board_Type KeyStone_Get_dsp_board_type() -{ - Uint32 deviceID= gpBootCfgRegs->DEVICE_ID_REG0&0x0FFFFFFF; - - gDSP_board_type= UNKNOWN; - if(0x0009D02F == deviceID) - gDSP_board_type= DUAL_NYQUIST_EVM; - if(0x0B94102F == deviceID) - { - gDSP_board_type= C6670_EVM; - //DSP_Board_Type= DUAL_NYQUIST_EVM; - } - if(0x0009E02F == deviceID) - gDSP_board_type= C6678_EVM; - if(0x0B96202F == deviceID) - gDSP_board_type= TCI6614_EVM; - if(0x0B97A02F == deviceID) - gDSP_board_type= C6657_EVM; - - return gDSP_board_type; -} - -static inline Uint32 KeyStone_Get_DSP_Number() -{ - TDSP_Board_Type DSP_Board_Type= KeyStone_Get_dsp_board_type(); - - if(DUAL_NYQUIST_EVM==DSP_Board_Type) - { - /*Nyquist EVM use boot configure pin 4 and 5 to identify DSPs*/ - return (( gpBootCfgRegs->BOOT_REG0 >> (3+1) ) & 0x03); - } - - /*if use DNUM to differentiate DSPs for two DSPs test, - the program must be run on core 0 of DSP 0 and core 1 of DSP1*/ - return DNUM; -} - -/*clear all interrupt flag/status, setup ISTP to begining of LL2*/ -extern void CPU_interrupt_init(); -/*enable interrupt to CPU: IER |= uiIER_en_mask; GIE=1*/ -extern void CPU_interrupt_enable(Uint32 uiIER_en_mask); - -//get device speed grade from the EFUSE register -extern void KeyStone_get_device_speed_grade(); - -/*Get device information including device type, boot mode, endian information, -speed grade, required voltage...*/ -extern void KeyStone_get_device_info(); - -/*common initialization for internal modules in K2 device. -enable memory protection interrupts, EDC for MSMC RAM*/ -extern void KeyStone_common_device_init(); - -/* enable TSC, EDC for local RAM; clear cache; protect L1 as cache */ -extern void KeyStone_common_CPU_init(); - - -#endif diff --git a/bsp/ti-tms320c6678/common/common.c b/bsp/ti-tms320c6678/common/common.c new file mode 100644 index 0000000000..0e026659ed --- /dev/null +++ b/bsp/ti-tms320c6678/common/common.c @@ -0,0 +1,201 @@ +/* + * Copyright (c) 2021, Shenzhen Academy of Aerospace Technology + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2021-11-16 Dystopia the first version + */ + +#include "common.h" + +CSL_BootcfgRegs * gpBootCfgRegs = (CSL_BootcfgRegs *)CSL_BOOT_CFG_REGS; +CSL_CgemRegs * gpCGEM_regs = (CSL_CgemRegs *)CSL_CGEM0_5_REG_BASE_ADDRESS_REGS; +CSL_TmrPlusRegs * gpTimerRegs[9] = { + (CSL_TmrPlusRegs *)CSL_TIMER_0_REGS, + (CSL_TmrPlusRegs *)CSL_TIMER_1_REGS, + (CSL_TmrPlusRegs *)CSL_TIMER_2_REGS, + (CSL_TmrPlusRegs *)CSL_TIMER_3_REGS, + (CSL_TmrPlusRegs *)CSL_TIMER_4_REGS, + (CSL_TmrPlusRegs *)CSL_TIMER_5_REGS, + (CSL_TmrPlusRegs *)CSL_TIMER_6_REGS, + (CSL_TmrPlusRegs *)CSL_TIMER_7_REGS, + (CSL_TmrPlusRegs *)(CSL_TIMER_7_REGS+(CSL_TIMER_7_REGS-CSL_TIMER_6_REGS)) +}; + +void cpu_interrupt_init(void) +{ + //clear interrupt and excpetion events + ICR = IFR; + ECR = EFR; + IER= 3; //disable all interrupts + + /* disable event combine */ + gpCGEM_regs->EVTMASK[0] = 0xffffffff; + gpCGEM_regs->EVTMASK[1] = 0xffffffff; + gpCGEM_regs->EVTMASK[2] = 0xffffffff; + gpCGEM_regs->EVTMASK[3] = 0xffffffff; + + /*Clear all CPU events*/ + gpCGEM_regs->EVTCLR[0]= 0xFFFFFFFF; + gpCGEM_regs->EVTCLR[1]= 0xFFFFFFFF; + gpCGEM_regs->EVTCLR[2]= 0xFFFFFFFF; + gpCGEM_regs->EVTCLR[3]= 0xFFFFFFFF; + + /*Interrupt Service Table Pointer to begining of LL2 memory*/ + ISTP= 0x800000; +} + +void keystone_cpu_init(void) +{ + /* clear all interrupt flag/status, setup ISTP to begining of LL2 */ + cpu_interrupt_init(); +} + +/*===============================Timer=================================*/ +void reset_timer(int timer_num) +{ + if(gpTimerRegs[timer_num]->TGCR) + { + gpTimerRegs[timer_num]->TGCR= 0; + gpTimerRegs[timer_num]->TCR= 0; + } +} + +void timer64_init(Timer64_Config * tmrCfg) +{ + reset_timer(tmrCfg->timer_num); + + gpTimerRegs[tmrCfg->timer_num]->CNTLO= 0; + gpTimerRegs[tmrCfg->timer_num]->CNTHI= 0; + + /*please note, in clock mode, two timer periods generate a clock, + one timer period output high voltage level, the other timer period + output low voltage level, so, the timer period should be half to the + desired output clock period*/ + if(TIMER_PERIODIC_CLOCK==tmrCfg->timerMode) + tmrCfg->period= tmrCfg->period/2; + + /*the value written into period register is the expected value minus one*/ + gpTimerRegs[tmrCfg->timer_num]->PRDLO= _loll(tmrCfg->period-1); + gpTimerRegs[tmrCfg->timer_num]->PRDHI= _hill(tmrCfg->period-1); + if(tmrCfg->reload_period>1) + { + gpTimerRegs[tmrCfg->timer_num]->RELLO= _loll(tmrCfg->reload_period-1); + gpTimerRegs[tmrCfg->timer_num]->RELHI= _hill(tmrCfg->reload_period-1); + } + + if(TIMER_WATCH_DOG==tmrCfg->timerMode) + { + gpTimerRegs[tmrCfg->timer_num]->TGCR= + /*Select watch-dog mode*/ + (CSL_TMR_TIMMODE_WDT<timerMode) + { + gpTimerRegs[tmrCfg->timer_num]->TGCR= TMR_TGCR_PLUSEN_MASK + /*for plus featuers, dual 32-bit unchained timer mode should be used*/ + |(CSL_TMR_TIMMODE_DUAL_UNCHAINED<timer_num]->INTCTL_STAT= TMR_INTCTLSTAT_EN_ALL_CLR_ALL; + } + else + { + gpTimerRegs[tmrCfg->timer_num]->TGCR= + /*Select 64-bit general timer mode*/ + (CSL_TMR_TIMMODE_GPT<timer_num]->EMUMGT_CLKSPD = (gpTimerRegs[tmrCfg->timer_num]->EMUMGT_CLKSPD& + ~(CSL_TMR_EMUMGT_CLKSPD_FREE_MASK|CSL_TMR_EMUMGT_CLKSPD_SOFT_MASK)); + + if(TIMER_WATCH_DOG==tmrCfg->timerMode) + { + /*enable watchdog timer*/ + gpTimerRegs[tmrCfg->timer_num]->WDTCR = CSL_TMR_WDTCR_WDEN_MASK + |(CSL_TMR_WDTCR_WDKEY_CMD1<timer_num]->TCR= + (CSL_TMR_CLOCK_INP_NOGATE<pulseWidth<timer_num]->WDTCR = CSL_TMR_WDTCR_WDEN_MASK + |(CSL_TMR_WDTCR_WDKEY_CMD2<timerMode) + { + gpTimerRegs[tmrCfg->timer_num]->TCR= + (CSL_TMR_CLOCK_INP_NOGATE<pulseWidth<timerMode) + { + gpTimerRegs[tmrCfg->timer_num]->TCR= + (CSL_TMR_CLOCK_INP_NOGATE<pulseWidth<timerMode) + { + gpTimerRegs[tmrCfg->timer_num]->TCR= + (CSL_TMR_CLOCK_INP_NOGATE<pulseWidth<timer_num]->TCR= + (CSL_TMR_CLOCK_INP_NOGATE<pulseWidth< +#include +#include +#include +#include +#include + +/* DSP core clock speed in Hz */ +#define DSP_CORE_SPEED_HZ 1000000000 + +extern CSL_CgemRegs * gpCGEM_regs; +extern CSL_BootcfgRegs * gpBootCfgRegs; + +/*----------------------Timer plus registers definition----------------*/ +typedef struct { + volatile unsigned int PID12; + volatile unsigned int EMUMGT_CLKSPD; + volatile unsigned int GPINT_EN; + volatile unsigned int GPDIR_DAT; + volatile unsigned int CNTLO; + volatile unsigned int CNTHI; + volatile unsigned int PRDLO; + volatile unsigned int PRDHI; + volatile unsigned int TCR; + volatile unsigned int TGCR; + volatile unsigned int WDTCR; + volatile unsigned int TLGC; + volatile unsigned int TLMR; + volatile unsigned int RELLO; + volatile unsigned int RELHI; + volatile unsigned int CAPLO; + volatile unsigned int CAPHI; + volatile unsigned int INTCTL_STAT; + volatile unsigned char RSVD0[24]; + volatile unsigned int TIMERLO_COMPARE_REG[8]; + volatile unsigned char RSVD1[32]; +} CSL_TmrPlusRegs; + +#define TMR_TCR_READRSTMODE_HI_SHIFT (26) +#define TMR_TCR_CAPEVTMODE_LO_SHIFT (12) +#define TMR_TCR_CAPMODE_LO_SHIFT (11) +#define TMR_TCR_READRSTMODE_LO_SHIFT (10) + +#define TMR_TCR_READRSTMODE_HI_MASK (1<<26) +#define TMR_TCR_CAPEVTMODE_LO_MASK (3<<12) +#define TMR_TCR_CAPMODE_LO_MASK (1<<11) +#define TMR_TCR_READRSTMODE_LO_MASK (1<<10) + +#define TMR_TGCR_PLUSEN_SHIFT 4 +#define TMR_TGCR_PLUSEN_MASK (1<<4) + +#define TMR_INTCTLSTAT_EN_ALL_CLR_ALL 0x000F000F + +#define CSL_TMR_WDTCR_WDKEY_CMD1 (0x0000A5C6u) +#define CSL_TMR_WDTCR_WDKEY_CMD2 (0x0000DA7Eu) + +#define CSL_TMR_ENAMODE_CONT_RELOAD 3 + +extern CSL_TmrPlusRegs * gpTimer0Regs; +extern CSL_TmrPlusRegs * gpTimer1Regs; +extern CSL_TmrPlusRegs * gpTimer2Regs; +extern CSL_TmrPlusRegs * gpTimer3Regs; +extern CSL_TmrPlusRegs * gpTimer4Regs; +extern CSL_TmrPlusRegs * gpTimer5Regs; +extern CSL_TmrPlusRegs * gpTimer6Regs; +extern CSL_TmrPlusRegs * gpTimer7Regs; +extern CSL_TmrPlusRegs * gpTimer8Regs; +extern CSL_TmrPlusRegs * gpTimerRegs[]; + +typedef enum +{ + TIMER_ONE_SHOT_PULSE = 0, /*generate one shot pulse with timer*/ + TIMER_PERIODIC_PULSE, /*generate periodic pulse with timer*/ + TIMER_PERIODIC_CLOCK, /*generate periodic clock with timer*/ + /*generate periodic square wave with period reload feature, the difference + between wave and clock is the duty cycle of clock is always 50%*/ + TIMER_PERIODIC_WAVE, + TIMER_WATCH_DOG /*configure timer as watch dog*/ +}TTimerMode; + +typedef struct { + int timer_num; /*select one timer*/ + TTimerMode timerMode; /*select function of the timer*/ + unsigned long long period; /*in the unit of DSP core clock/6*/ + unsigned long long reload_period; /*the reload value of period*/ + int pulseWidth; /*pulse width between 0~3*/ +}Timer64_Config; + +/* Reset a 64-bit timer */ +extern void reset_timer(int timer_num); + +/* Initailize a 64-bit timer */ +extern void timer64_init(Timer64_Config * tmrCfg); + +extern void keystone_cpu_init(void); + +#endif /* __COMMON_H__ */ diff --git a/bsp/ti-tms320c6678/driver/drv_timer.c b/bsp/ti-tms320c6678/driver/drv_timer.c index 9fe4e05fed..08915ef966 100644 --- a/bsp/ti-tms320c6678/driver/drv_timer.c +++ b/bsp/ti-tms320c6678/driver/drv_timer.c @@ -9,7 +9,8 @@ */ #include "drv_timer.h" -#include "KeyStone_common.h" +#include "interrupt.h" +#include "common.h" #include #include @@ -37,7 +38,7 @@ void rt_hw_system_timer_init(void) // initial system timer interrupt, map local timer interrupt to INT14 gpCGEM_regs->INTMUX3 = (CSL_GEM_TINTLN << CSL_CGEM_INTMUX3_INTSEL14_SHIFT); // enable CPU INT14 - CPU_interrupt_enable(1 << 14); + rt_hw_interrupt_umask(1 << 14); return ; } @@ -57,9 +58,9 @@ void rt_hw_system_timer_start(void) // configure the timer to generate clocks and interrupts tmrCfg.timer_num = DNUM; tmrCfg.timerMode = TIMER_PERIODIC_CLOCK; - tmrCfg.period = (unsigned long long) RT_TICK_PER_SECOND * gDSP_Core_Speed_Hz / 6000; + tmrCfg.period = (unsigned long long) RT_TICK_PER_SECOND * DSP_CORE_SPEED_HZ / 6000; tmrCfg.reload_period = 0; // initial timer - Timer64_Init(&tmrCfg); + timer64_init(&tmrCfg); } diff --git a/bsp/ti-tms320c6678/driver/drv_timer.h b/bsp/ti-tms320c6678/driver/drv_timer.h index f30dd940da..d663a5bb67 100644 --- a/bsp/ti-tms320c6678/driver/drv_timer.h +++ b/bsp/ti-tms320c6678/driver/drv_timer.h @@ -11,6 +11,9 @@ #ifndef __SYS_TIMER_H__ #define __SYS_TIMER_H__ +#include +#include + void rt_hw_system_timer_init(void); void rt_hw_system_timer_start(void); diff --git a/libcpu/ti-dsp/c6x/c66xx.h b/libcpu/ti-dsp/c6x/c66xx.h index 903edbfaf1..b69561c163 100644 --- a/libcpu/ti-dsp/c6x/c66xx.h +++ b/libcpu/ti-dsp/c6x/c66xx.h @@ -11,15 +11,25 @@ #ifndef __C66XX_H__ #define __C66XX_H__ -extern cregister volatile unsigned int IERR; /* Internal Exception Report Register */ -extern cregister volatile unsigned int ECR; /* Exception Clear Register */ -extern cregister volatile unsigned int EFR; /* Exception Flag Register */ -extern cregister volatile unsigned int TSR; /* Task State Register */ -extern cregister volatile unsigned int ITSR; /* Interrupt Task State Register */ -extern cregister volatile unsigned int NTSR; /* NMI/exception Task State Register */ -extern cregister volatile unsigned int TSCL; /* Time Stamp Counter Register - Low Half */ -extern cregister volatile unsigned int TSCH; /* Time Stamp Counter Register - High Half */ -extern cregister volatile unsigned int DNUM; /* Core number */ +extern __cregister volatile unsigned int IERR; /* Internal Exception Report Register */ +extern __cregister volatile unsigned int ECR; /* Exception Clear Register */ +extern __cregister volatile unsigned int EFR; /* Exception Flag Register */ +extern __cregister volatile unsigned int TSR; /* Task State Register */ +extern __cregister volatile unsigned int ITSR; /* Interrupt Task State Register */ +extern __cregister volatile unsigned int NTSR; /* NMI/exception Task State Register */ +extern __cregister volatile unsigned int TSCL; /* Time Stamp Counter Register - Low Half */ +extern __cregister volatile unsigned int TSCH; /* Time Stamp Counter Register - High Half */ +extern __cregister volatile unsigned int DNUM; /* Core number */ + +extern __cregister volatile unsigned int AMR; +extern __cregister volatile unsigned int CSR; +extern __cregister volatile unsigned int IFR; +extern __cregister volatile unsigned int ISR; +extern __cregister volatile unsigned int ICR; +extern __cregister volatile unsigned int IER; +extern __cregister volatile unsigned int ISTP; +extern __cregister volatile unsigned int IRP; +extern __cregister volatile unsigned int NRP; #ifdef _BIG_ENDIAN #define RT_REG_PAIR(odd, even) unsigned long odd; unsigned long even diff --git a/libcpu/ti-dsp/c6x/interrupt.c b/libcpu/ti-dsp/c6x/interrupt.c index 1f532f6c32..6e48cb8efa 100644 --- a/libcpu/ti-dsp/c6x/interrupt.c +++ b/libcpu/ti-dsp/c6x/interrupt.c @@ -60,6 +60,11 @@ void rt_hw_interrupt_umask(int vector) { return; } + ICR = vector; + IER |= vector; + + //enable GIE + TSR = TSR | 1; } /** From b8db37f53f3546594fe151894024ae15fbcb7904 Mon Sep 17 00:00:00 2001 From: Huang bo Date: Wed, 15 Dec 2021 10:55:24 +0800 Subject: [PATCH 15/24] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E6=A0=BC=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- bsp/ti-tms320c6678/applications/board.c | 2 +- bsp/ti-tms320c6678/common/common.c | 146 ++++++++++++------------ 2 files changed, 75 insertions(+), 73 deletions(-) diff --git a/bsp/ti-tms320c6678/applications/board.c b/bsp/ti-tms320c6678/applications/board.c index 0e622765da..bfa4057c1f 100644 --- a/bsp/ti-tms320c6678/applications/board.c +++ b/bsp/ti-tms320c6678/applications/board.c @@ -21,7 +21,7 @@ void rt_hw_board_init(void) { // initial CPU core - keystone_cpu_init(); + keystone_cpu_init(); // initial interrupt controller rt_hw_interrupt_init(); diff --git a/bsp/ti-tms320c6678/common/common.c b/bsp/ti-tms320c6678/common/common.c index 0e026659ed..66826e2183 100644 --- a/bsp/ti-tms320c6678/common/common.c +++ b/bsp/ti-tms320c6678/common/common.c @@ -58,7 +58,7 @@ void reset_timer(int timer_num) { if(gpTimerRegs[timer_num]->TGCR) { - gpTimerRegs[timer_num]->TGCR= 0; + gpTimerRegs[timer_num]->TGCR = 0; gpTimerRegs[timer_num]->TCR= 0; } } @@ -67,135 +67,137 @@ void timer64_init(Timer64_Config * tmrCfg) { reset_timer(tmrCfg->timer_num); - gpTimerRegs[tmrCfg->timer_num]->CNTLO= 0; - gpTimerRegs[tmrCfg->timer_num]->CNTHI= 0; + gpTimerRegs[tmrCfg->timer_num]->CNTLO = 0; + gpTimerRegs[tmrCfg->timer_num]->CNTHI = 0; /*please note, in clock mode, two timer periods generate a clock, one timer period output high voltage level, the other timer period output low voltage level, so, the timer period should be half to the desired output clock period*/ - if(TIMER_PERIODIC_CLOCK==tmrCfg->timerMode) - tmrCfg->period= tmrCfg->period/2; + if(TIMER_PERIODIC_CLOCK == tmrCfg->timerMode) + { + tmrCfg->period = tmrCfg->period/2; + } /*the value written into period register is the expected value minus one*/ - gpTimerRegs[tmrCfg->timer_num]->PRDLO= _loll(tmrCfg->period-1); - gpTimerRegs[tmrCfg->timer_num]->PRDHI= _hill(tmrCfg->period-1); + gpTimerRegs[tmrCfg->timer_num]->PRDLO = _loll(tmrCfg->period-1); + gpTimerRegs[tmrCfg->timer_num]->PRDHI = _hill(tmrCfg->period-1); if(tmrCfg->reload_period>1) { - gpTimerRegs[tmrCfg->timer_num]->RELLO= _loll(tmrCfg->reload_period-1); - gpTimerRegs[tmrCfg->timer_num]->RELHI= _hill(tmrCfg->reload_period-1); + gpTimerRegs[tmrCfg->timer_num]->RELLO = _loll(tmrCfg->reload_period-1); + gpTimerRegs[tmrCfg->timer_num]->RELHI = _hill(tmrCfg->reload_period-1); } - if(TIMER_WATCH_DOG==tmrCfg->timerMode) + if(TIMER_WATCH_DOG == tmrCfg->timerMode) { - gpTimerRegs[tmrCfg->timer_num]->TGCR= + gpTimerRegs[tmrCfg->timer_num]->TGCR = /*Select watch-dog mode*/ - (CSL_TMR_TIMMODE_WDT<timerMode) + else if(TIMER_PERIODIC_WAVE == tmrCfg->timerMode) { - gpTimerRegs[tmrCfg->timer_num]->TGCR= TMR_TGCR_PLUSEN_MASK + gpTimerRegs[tmrCfg->timer_num]->TGCR = TMR_TGCR_PLUSEN_MASK /*for plus featuers, dual 32-bit unchained timer mode should be used*/ - |(CSL_TMR_TIMMODE_DUAL_UNCHAINED<timer_num]->INTCTL_STAT= TMR_INTCTLSTAT_EN_ALL_CLR_ALL; } else { - gpTimerRegs[tmrCfg->timer_num]->TGCR= + gpTimerRegs[tmrCfg->timer_num]->TGCR = /*Select 64-bit general timer mode*/ - (CSL_TMR_TIMMODE_GPT<timer_num]->EMUMGT_CLKSPD = (gpTimerRegs[tmrCfg->timer_num]->EMUMGT_CLKSPD& ~(CSL_TMR_EMUMGT_CLKSPD_FREE_MASK|CSL_TMR_EMUMGT_CLKSPD_SOFT_MASK)); - if(TIMER_WATCH_DOG==tmrCfg->timerMode) + if(TIMER_WATCH_DOG == tmrCfg->timerMode) { /*enable watchdog timer*/ gpTimerRegs[tmrCfg->timer_num]->WDTCR = CSL_TMR_WDTCR_WDEN_MASK - |(CSL_TMR_WDTCR_WDKEY_CMD1<timer_num]->TCR= - (CSL_TMR_CLOCK_INP_NOGATE<pulseWidth<pulseWidth << CSL_TMR_TCR_PWID_LO_SHIFT)&CSL_TMR_TCR_PWID_LO_MASK) /*select pulse mode*/ - |(CSL_TMR_CP_PULSE<timer_num]->WDTCR = CSL_TMR_WDTCR_WDEN_MASK - |(CSL_TMR_WDTCR_WDKEY_CMD2<timerMode) + else if(TIMER_ONE_SHOT_PULSE == tmrCfg->timerMode) { - gpTimerRegs[tmrCfg->timer_num]->TCR= - (CSL_TMR_CLOCK_INP_NOGATE<timer_num]->TCR = + (CSL_TMR_CLOCK_INP_NOGATE << CSL_TMR_TCR_TIEN_LO_SHIFT) + | (CSL_TMR_CLKSRC_INTERNAL << CSL_TMR_TCR_CLKSRC_LO_SHIFT) /*The timer is enabled one-shot*/ - |(CSL_TMR_ENAMODE_ENABLE<pulseWidth<pulseWidth << CSL_TMR_TCR_PWID_LO_SHIFT)&CSL_TMR_TCR_PWID_LO_MASK) /*select pulse mode*/ - |(CSL_TMR_CP_PULSE<timerMode) + else if(TIMER_PERIODIC_CLOCK == tmrCfg->timerMode) { - gpTimerRegs[tmrCfg->timer_num]->TCR= - (CSL_TMR_CLOCK_INP_NOGATE<timer_num]->TCR = + (CSL_TMR_CLOCK_INP_NOGATE << CSL_TMR_TCR_TIEN_LO_SHIFT) + | (CSL_TMR_CLKSRC_INTERNAL << CSL_TMR_TCR_CLKSRC_LO_SHIFT) /*The timer is enabled continuously*/ - |(CSL_TMR_ENAMODE_CONT<pulseWidth<pulseWidth << CSL_TMR_TCR_PWID_LO_SHIFT)&CSL_TMR_TCR_PWID_LO_MASK) /*select clock mode*/ - |(CSL_TMR_CP_CLOCK<timerMode) + else if(TIMER_PERIODIC_WAVE == tmrCfg->timerMode) { - gpTimerRegs[tmrCfg->timer_num]->TCR= - (CSL_TMR_CLOCK_INP_NOGATE<timer_num]->TCR = + (CSL_TMR_CLOCK_INP_NOGATE << CSL_TMR_TCR_TIEN_LO_SHIFT) + | (CSL_TMR_CLKSRC_INTERNAL << CSL_TMR_TCR_CLKSRC_LO_SHIFT) /*The timer is enabled continuously with period reload*/ - |(CSL_TMR_ENAMODE_CONT_RELOAD<pulseWidth<pulseWidth << CSL_TMR_TCR_PWID_LO_SHIFT)&CSL_TMR_TCR_PWID_LO_MASK) /*select clock mode*/ - |(CSL_TMR_CP_CLOCK<timer_num]->TCR= - (CSL_TMR_CLOCK_INP_NOGATE<timer_num]->TCR = + (CSL_TMR_CLOCK_INP_NOGATE << CSL_TMR_TCR_TIEN_LO_SHIFT) + | (CSL_TMR_CLKSRC_INTERNAL << CSL_TMR_TCR_CLKSRC_LO_SHIFT) /*The timer is enabled continuously*/ - |(CSL_TMR_ENAMODE_CONT<pulseWidth<pulseWidth << CSL_TMR_TCR_PWID_LO_SHIFT)&CSL_TMR_TCR_PWID_LO_MASK) /*select clock mode*/ - |(CSL_TMR_CP_PULSE< Date: Wed, 15 Dec 2021 11:10:13 +0800 Subject: [PATCH 16/24] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E6=A0=BC=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- bsp/ti-tms320c6678/common/common.c | 68 +++++++++++++-------------- bsp/ti-tms320c6678/common/common.h | 24 +++++----- bsp/ti-tms320c6678/driver/drv_timer.c | 6 +-- 3 files changed, 49 insertions(+), 49 deletions(-) diff --git a/bsp/ti-tms320c6678/common/common.c b/bsp/ti-tms320c6678/common/common.c index 66826e2183..1c362d76f8 100644 --- a/bsp/ti-tms320c6678/common/common.c +++ b/bsp/ti-tms320c6678/common/common.c @@ -10,9 +10,9 @@ #include "common.h" -CSL_BootcfgRegs * gpBootCfgRegs = (CSL_BootcfgRegs *)CSL_BOOT_CFG_REGS; -CSL_CgemRegs * gpCGEM_regs = (CSL_CgemRegs *)CSL_CGEM0_5_REG_BASE_ADDRESS_REGS; -CSL_TmrPlusRegs * gpTimerRegs[9] = { +CSL_BootcfgRegs * gp_bootcfg_regs = (CSL_BootcfgRegs *)CSL_BOOT_CFG_REGS; +CSL_CgemRegs * gp_cgem_regs = (CSL_CgemRegs *)CSL_CGEM0_5_REG_BASE_ADDRESS_REGS; +CSL_TmrPlusRegs * gp_timer_regs[9] = { (CSL_TmrPlusRegs *)CSL_TIMER_0_REGS, (CSL_TmrPlusRegs *)CSL_TIMER_1_REGS, (CSL_TmrPlusRegs *)CSL_TIMER_2_REGS, @@ -29,22 +29,22 @@ void cpu_interrupt_init(void) //clear interrupt and excpetion events ICR = IFR; ECR = EFR; - IER= 3; //disable all interrupts + IER = 3; //disable all interrupts /* disable event combine */ - gpCGEM_regs->EVTMASK[0] = 0xffffffff; - gpCGEM_regs->EVTMASK[1] = 0xffffffff; - gpCGEM_regs->EVTMASK[2] = 0xffffffff; - gpCGEM_regs->EVTMASK[3] = 0xffffffff; + gp_cgem_regs->EVTMASK[0] = 0xffffffff; + gp_cgem_regs->EVTMASK[1] = 0xffffffff; + gp_cgem_regs->EVTMASK[2] = 0xffffffff; + gp_cgem_regs->EVTMASK[3] = 0xffffffff; /*Clear all CPU events*/ - gpCGEM_regs->EVTCLR[0]= 0xFFFFFFFF; - gpCGEM_regs->EVTCLR[1]= 0xFFFFFFFF; - gpCGEM_regs->EVTCLR[2]= 0xFFFFFFFF; - gpCGEM_regs->EVTCLR[3]= 0xFFFFFFFF; + gp_cgem_regs->EVTCLR[0] = 0xFFFFFFFF; + gp_cgem_regs->EVTCLR[1] = 0xFFFFFFFF; + gp_cgem_regs->EVTCLR[2] = 0xFFFFFFFF; + gp_cgem_regs->EVTCLR[3] = 0xFFFFFFFF; /*Interrupt Service Table Pointer to begining of LL2 memory*/ - ISTP= 0x800000; + ISTP = 0x800000; } void keystone_cpu_init(void) @@ -56,10 +56,10 @@ void keystone_cpu_init(void) /*===============================Timer=================================*/ void reset_timer(int timer_num) { - if(gpTimerRegs[timer_num]->TGCR) + if(gp_timer_regs[timer_num]->TGCR) { - gpTimerRegs[timer_num]->TGCR = 0; - gpTimerRegs[timer_num]->TCR= 0; + gp_timer_regs[timer_num]->TGCR = 0; + gp_timer_regs[timer_num]->TCR= 0; } } @@ -67,8 +67,8 @@ void timer64_init(Timer64_Config * tmrCfg) { reset_timer(tmrCfg->timer_num); - gpTimerRegs[tmrCfg->timer_num]->CNTLO = 0; - gpTimerRegs[tmrCfg->timer_num]->CNTHI = 0; + gp_timer_regs[tmrCfg->timer_num]->CNTLO = 0; + gp_timer_regs[tmrCfg->timer_num]->CNTHI = 0; /*please note, in clock mode, two timer periods generate a clock, one timer period output high voltage level, the other timer period @@ -80,17 +80,17 @@ void timer64_init(Timer64_Config * tmrCfg) } /*the value written into period register is the expected value minus one*/ - gpTimerRegs[tmrCfg->timer_num]->PRDLO = _loll(tmrCfg->period-1); - gpTimerRegs[tmrCfg->timer_num]->PRDHI = _hill(tmrCfg->period-1); + gp_timer_regs[tmrCfg->timer_num]->PRDLO = _loll(tmrCfg->period-1); + gp_timer_regs[tmrCfg->timer_num]->PRDHI = _hill(tmrCfg->period-1); if(tmrCfg->reload_period>1) { - gpTimerRegs[tmrCfg->timer_num]->RELLO = _loll(tmrCfg->reload_period-1); - gpTimerRegs[tmrCfg->timer_num]->RELHI = _hill(tmrCfg->reload_period-1); + gp_timer_regs[tmrCfg->timer_num]->RELLO = _loll(tmrCfg->reload_period-1); + gp_timer_regs[tmrCfg->timer_num]->RELHI = _hill(tmrCfg->reload_period-1); } if(TIMER_WATCH_DOG == tmrCfg->timerMode) { - gpTimerRegs[tmrCfg->timer_num]->TGCR = + gp_timer_regs[tmrCfg->timer_num]->TGCR = /*Select watch-dog mode*/ (CSL_TMR_TIMMODE_WDT << CSL_TMR_TGCR_TIMMODE_SHIFT) /*Remove the timer from reset*/ @@ -99,18 +99,18 @@ void timer64_init(Timer64_Config * tmrCfg) } else if(TIMER_PERIODIC_WAVE == tmrCfg->timerMode) { - gpTimerRegs[tmrCfg->timer_num]->TGCR = TMR_TGCR_PLUSEN_MASK + gp_timer_regs[tmrCfg->timer_num]->TGCR = TMR_TGCR_PLUSEN_MASK /*for plus featuers, dual 32-bit unchained timer mode should be used*/ | (CSL_TMR_TIMMODE_DUAL_UNCHAINED << CSL_TMR_TGCR_TIMMODE_SHIFT) /*Remove the timer from reset*/ | (CSL_TMR_TGCR_TIMLORS_MASK); //in plus mode, interrupt/event must be enabled manually - gpTimerRegs[tmrCfg->timer_num]->INTCTL_STAT= TMR_INTCTLSTAT_EN_ALL_CLR_ALL; + gp_timer_regs[tmrCfg->timer_num]->INTCTL_STAT= TMR_INTCTLSTAT_EN_ALL_CLR_ALL; } else { - gpTimerRegs[tmrCfg->timer_num]->TGCR = + gp_timer_regs[tmrCfg->timer_num]->TGCR = /*Select 64-bit general timer mode*/ (CSL_TMR_TIMMODE_GPT << CSL_TMR_TGCR_TIMMODE_SHIFT) /*Remove the timer from reset*/ @@ -119,16 +119,16 @@ void timer64_init(Timer64_Config * tmrCfg) } /*make timer stop with emulation*/ - gpTimerRegs[tmrCfg->timer_num]->EMUMGT_CLKSPD = (gpTimerRegs[tmrCfg->timer_num]->EMUMGT_CLKSPD& + gp_timer_regs[tmrCfg->timer_num]->EMUMGT_CLKSPD = (gp_timer_regs[tmrCfg->timer_num]->EMUMGT_CLKSPD& ~(CSL_TMR_EMUMGT_CLKSPD_FREE_MASK|CSL_TMR_EMUMGT_CLKSPD_SOFT_MASK)); if(TIMER_WATCH_DOG == tmrCfg->timerMode) { /*enable watchdog timer*/ - gpTimerRegs[tmrCfg->timer_num]->WDTCR = CSL_TMR_WDTCR_WDEN_MASK + gp_timer_regs[tmrCfg->timer_num]->WDTCR = CSL_TMR_WDTCR_WDEN_MASK | (CSL_TMR_WDTCR_WDKEY_CMD1 << CSL_TMR_WDTCR_WDKEY_SHIFT); - gpTimerRegs[tmrCfg->timer_num]->TCR= + gp_timer_regs[tmrCfg->timer_num]->TCR = (CSL_TMR_CLOCK_INP_NOGATE << CSL_TMR_TCR_TIEN_LO_SHIFT) | (CSL_TMR_CLKSRC_INTERNAL << CSL_TMR_TCR_CLKSRC_LO_SHIFT) /*The timer is enabled continuously*/ @@ -141,12 +141,12 @@ void timer64_init(Timer64_Config * tmrCfg) | (0 << CSL_TMR_TCR_TSTAT_LO_SHIFT); /*active watchdog timer*/ - gpTimerRegs[tmrCfg->timer_num]->WDTCR = CSL_TMR_WDTCR_WDEN_MASK + gp_timer_regs[tmrCfg->timer_num]->WDTCR = CSL_TMR_WDTCR_WDEN_MASK | (CSL_TMR_WDTCR_WDKEY_CMD2 << CSL_TMR_WDTCR_WDKEY_SHIFT); } else if(TIMER_ONE_SHOT_PULSE == tmrCfg->timerMode) { - gpTimerRegs[tmrCfg->timer_num]->TCR = + gp_timer_regs[tmrCfg->timer_num]->TCR = (CSL_TMR_CLOCK_INP_NOGATE << CSL_TMR_TCR_TIEN_LO_SHIFT) | (CSL_TMR_CLKSRC_INTERNAL << CSL_TMR_TCR_CLKSRC_LO_SHIFT) /*The timer is enabled one-shot*/ @@ -160,7 +160,7 @@ void timer64_init(Timer64_Config * tmrCfg) } else if(TIMER_PERIODIC_CLOCK == tmrCfg->timerMode) { - gpTimerRegs[tmrCfg->timer_num]->TCR = + gp_timer_regs[tmrCfg->timer_num]->TCR = (CSL_TMR_CLOCK_INP_NOGATE << CSL_TMR_TCR_TIEN_LO_SHIFT) | (CSL_TMR_CLKSRC_INTERNAL << CSL_TMR_TCR_CLKSRC_LO_SHIFT) /*The timer is enabled continuously*/ @@ -174,7 +174,7 @@ void timer64_init(Timer64_Config * tmrCfg) } else if(TIMER_PERIODIC_WAVE == tmrCfg->timerMode) { - gpTimerRegs[tmrCfg->timer_num]->TCR = + gp_timer_regs[tmrCfg->timer_num]->TCR = (CSL_TMR_CLOCK_INP_NOGATE << CSL_TMR_TCR_TIEN_LO_SHIFT) | (CSL_TMR_CLKSRC_INTERNAL << CSL_TMR_TCR_CLKSRC_LO_SHIFT) /*The timer is enabled continuously with period reload*/ @@ -188,7 +188,7 @@ void timer64_init(Timer64_Config * tmrCfg) } else /*TIMER_PERIODIC_PULSE*/ { - gpTimerRegs[tmrCfg->timer_num]->TCR = + gp_timer_regs[tmrCfg->timer_num]->TCR = (CSL_TMR_CLOCK_INP_NOGATE << CSL_TMR_TCR_TIEN_LO_SHIFT) | (CSL_TMR_CLKSRC_INTERNAL << CSL_TMR_TCR_CLKSRC_LO_SHIFT) /*The timer is enabled continuously*/ diff --git a/bsp/ti-tms320c6678/common/common.h b/bsp/ti-tms320c6678/common/common.h index d75063903d..61da9ca25a 100644 --- a/bsp/ti-tms320c6678/common/common.h +++ b/bsp/ti-tms320c6678/common/common.h @@ -21,8 +21,8 @@ /* DSP core clock speed in Hz */ #define DSP_CORE_SPEED_HZ 1000000000 -extern CSL_CgemRegs * gpCGEM_regs; -extern CSL_BootcfgRegs * gpBootCfgRegs; +extern CSL_CgemRegs * gp_cgem_regs; +extern CSL_BootcfgRegs * gp_bootcfg_regs; /*----------------------Timer plus registers definition----------------*/ typedef struct { @@ -69,16 +69,16 @@ typedef struct { #define CSL_TMR_ENAMODE_CONT_RELOAD 3 -extern CSL_TmrPlusRegs * gpTimer0Regs; -extern CSL_TmrPlusRegs * gpTimer1Regs; -extern CSL_TmrPlusRegs * gpTimer2Regs; -extern CSL_TmrPlusRegs * gpTimer3Regs; -extern CSL_TmrPlusRegs * gpTimer4Regs; -extern CSL_TmrPlusRegs * gpTimer5Regs; -extern CSL_TmrPlusRegs * gpTimer6Regs; -extern CSL_TmrPlusRegs * gpTimer7Regs; -extern CSL_TmrPlusRegs * gpTimer8Regs; -extern CSL_TmrPlusRegs * gpTimerRegs[]; +extern CSL_TmrPlusRegs * gp_timer0_regs; +extern CSL_TmrPlusRegs * gp_timer1_regs; +extern CSL_TmrPlusRegs * gp_timer2_regs; +extern CSL_TmrPlusRegs * gp_timer3_regs; +extern CSL_TmrPlusRegs * gp_timer4_regs; +extern CSL_TmrPlusRegs * gp_timer5_regs; +extern CSL_TmrPlusRegs * gp_timer6_regs; +extern CSL_TmrPlusRegs * gp_timer7_regs; +extern CSL_TmrPlusRegs * gp_timer8_regs; +extern CSL_TmrPlusRegs * gp_timer_regs[]; typedef enum { diff --git a/bsp/ti-tms320c6678/driver/drv_timer.c b/bsp/ti-tms320c6678/driver/drv_timer.c index 08915ef966..fe8aca1273 100644 --- a/bsp/ti-tms320c6678/driver/drv_timer.c +++ b/bsp/ti-tms320c6678/driver/drv_timer.c @@ -36,7 +36,7 @@ void rt_hw_systick_isr(void) void rt_hw_system_timer_init(void) { // initial system timer interrupt, map local timer interrupt to INT14 - gpCGEM_regs->INTMUX3 = (CSL_GEM_TINTLN << CSL_CGEM_INTMUX3_INTSEL14_SHIFT); + gp_cgem_regs->INTMUX3 = (CSL_GEM_TINTLN << CSL_CGEM_INTMUX3_INTSEL14_SHIFT); // enable CPU INT14 rt_hw_interrupt_umask(1 << 14); @@ -45,7 +45,7 @@ void rt_hw_system_timer_init(void) /** * The function initial system timer. - * Use local timer (==DNUM of a core) to generate a clock on TIMO0,interrupts are generated as well + * Use local timer (== DNUM of a core) to generate a clock on TIMO0,interrupts are generated as well * */ void rt_hw_system_timer_start(void) @@ -53,7 +53,7 @@ void rt_hw_system_timer_start(void) Timer64_Config tmrCfg; // select output on TIMO0 from local timer. - gpBootCfgRegs->TOUTSEL = (DNUM*2) << CSL_BOOTCFG_TOUTSEL_TOUTSEL0_SHIFT; + gp_bootcfg_regs->TOUTSEL = (DNUM*2) << CSL_BOOTCFG_TOUTSEL_TOUTSEL0_SHIFT; // configure the timer to generate clocks and interrupts tmrCfg.timer_num = DNUM; From 457fcecda9fba7b862214ef58bf8837636757bbc Mon Sep 17 00:00:00 2001 From: Huang bo Date: Wed, 29 Dec 2021 09:23:17 +0800 Subject: [PATCH 17/24] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E7=BC=96=E8=AF=91?= =?UTF-8?q?=E8=AF=B4=E6=98=8E?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- bsp/ti-tms320c6678/.cproject | 94 +++++++++--------- .../org.eclipse.core.resources.prefs | 12 +++ bsp/ti-tms320c6678/figures/debug(1).png | Bin 0 -> 25508 bytes bsp/ti-tms320c6678/figures/debug(2).png | Bin 0 -> 56653 bytes bsp/ti-tms320c6678/figures/filepath.png | Bin 0 -> 12891 bytes bsp/ti-tms320c6678/figures/general.jpg | Bin 0 -> 21087 bytes bsp/ti-tms320c6678/figures/import(1).png | Bin 0 -> 37130 bytes bsp/ti-tms320c6678/figures/import(2).png | Bin 0 -> 25813 bytes bsp/ti-tms320c6678/figures/load.png | Bin 0 -> 61832 bytes bsp/ti-tms320c6678/readme.txt | 2 +- 10 files changed, 62 insertions(+), 46 deletions(-) create mode 100644 bsp/ti-tms320c6678/.settings/org.eclipse.core.resources.prefs create mode 100644 bsp/ti-tms320c6678/figures/debug(1).png create mode 100644 bsp/ti-tms320c6678/figures/debug(2).png create mode 100644 bsp/ti-tms320c6678/figures/filepath.png create mode 100644 bsp/ti-tms320c6678/figures/general.jpg create mode 100644 bsp/ti-tms320c6678/figures/import(1).png create mode 100644 bsp/ti-tms320c6678/figures/import(2).png create mode 100644 bsp/ti-tms320c6678/figures/load.png diff --git a/bsp/ti-tms320c6678/.cproject b/bsp/ti-tms320c6678/.cproject index 0c4124a28d..a906191430 100644 --- a/bsp/ti-tms320c6678/.cproject +++ b/bsp/ti-tms320c6678/.cproject @@ -16,27 +16,24 @@ - - @@ -98,36 +99,36 @@ - diff --git a/bsp/ti-tms320c6678/.settings/org.eclipse.core.resources.prefs b/bsp/ti-tms320c6678/.settings/org.eclipse.core.resources.prefs new file mode 100644 index 0000000000..243442d787 --- /dev/null +++ b/bsp/ti-tms320c6678/.settings/org.eclipse.core.resources.prefs @@ -0,0 +1,12 @@ +eclipse.preferences.version=1 +encoding//Debug/applications/subdir_rules.mk=UTF-8 +encoding//Debug/applications/subdir_vars.mk=UTF-8 +encoding//Debug/common/subdir_rules.mk=UTF-8 +encoding//Debug/common/subdir_vars.mk=UTF-8 +encoding//Debug/driver/subdir_rules.mk=UTF-8 +encoding//Debug/driver/subdir_vars.mk=UTF-8 +encoding//Debug/makefile=UTF-8 +encoding//Debug/objects.mk=UTF-8 +encoding//Debug/sources.mk=UTF-8 +encoding//Debug/subdir_rules.mk=UTF-8 +encoding//Debug/subdir_vars.mk=UTF-8 diff --git a/bsp/ti-tms320c6678/figures/debug(1).png b/bsp/ti-tms320c6678/figures/debug(1).png new file mode 100644 index 0000000000000000000000000000000000000000..00f7616b49ffe59e721bd7b7b64d3f149afb09a7 GIT binary patch literal 25508 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 O#}1u5nEmrb%)bH97l{G@ literal 0 HcmV?d00001 diff --git a/bsp/ti-tms320c6678/figures/debug(2).png b/bsp/ti-tms320c6678/figures/debug(2).png new file mode 100644 index 0000000000000000000000000000000000000000..35d6f4e85ffaf6fa231a27605d00d1fa83227d41 GIT binary patch literal 56653 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 literal 0 HcmV?d00001 diff --git a/bsp/ti-tms320c6678/figures/filepath.png b/bsp/ti-tms320c6678/figures/filepath.png new file mode 100644 index 0000000000000000000000000000000000000000..71a11da2fd7ea3a1cfb378bf33b80374a78b399f GIT binary patch literal 12891 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 IbxsLQ0FXPorvLx| literal 0 HcmV?d00001 diff --git a/bsp/ti-tms320c6678/figures/import(1).png b/bsp/ti-tms320c6678/figures/import(1).png new file mode 100644 index 0000000000000000000000000000000000000000..9bc4eac5d2c827c8af9aeaabf466fc83762a08ef GIT binary patch literal 37130 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 Re9HIAq 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 literal 0 HcmV?d00001 diff --git a/bsp/ti-tms320c6678/figures/load.png b/bsp/ti-tms320c6678/figures/load.png new file mode 100644 index 0000000000000000000000000000000000000000..99d3b5f51c8ebe62e90fffbaf37c205a7c321547 GIT binary patch literal 61832 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 SiM7Z7Qt^hGJW}@V Date: Thu, 27 Jan 2022 13:57:07 +0000 Subject: [PATCH 18/24] rename bsp/ti-tms320c6678/readme.txt to bsp/ti-tms320c6678/README.md. --- bsp/ti-tms320c6678/README.md | 13 +++++++++++++ bsp/ti-tms320c6678/readme.txt | 4 ---- 2 files changed, 13 insertions(+), 4 deletions(-) create mode 100644 bsp/ti-tms320c6678/README.md delete mode 100644 bsp/ti-tms320c6678/readme.txt diff --git a/bsp/ti-tms320c6678/README.md b/bsp/ti-tms320c6678/README.md new file mode 100644 index 0000000000..ca8195b661 --- /dev/null +++ b/bsp/ti-tms320c6678/README.md @@ -0,0 +1,13 @@ + +# 1.简介 + TMS320C6678是TI基于KeyStone的多核固定浮点数字信号处理器,DSP集成C66x CorePac,每个核心在1至1.25 GHz到10 GHz的运行。 +该设备支持高性能的信号处理应用,如任务关键,医疗成像,测试和自动化。 + +## 2.编译说明 + TMS320C6678 工程的编译和下载要使用的是 TI 官方提供的 Code Composer Studio。在本工程使用的是 CCS5.5 版本编译调试, +CCS5.5 Compiler version:TIv8.3.5进行编译,需要安装TI提供的CSL库pdk_C6678_1_1_2_6。 + +pdk_C6678_1_1_2_6安装路径为: +"C:\ti\pdk_C6678_1_1_2_6\packages" +"C:\ti\pdk_C6678_1_1_2_6\packages\ti\csl" + diff --git a/bsp/ti-tms320c6678/readme.txt b/bsp/ti-tms320c6678/readme.txt deleted file mode 100644 index aa677425d5..0000000000 --- a/bsp/ti-tms320c6678/readme.txt +++ /dev/null @@ -1,4 +0,0 @@ - 本工程使用TI公司编译器CCS5.5 Compiler version:TIv8.3.5进行编译,需要安装TI提供的CSL库pdk_C6678_1_1_2_6, -我的安装路径为C盘。 -"C:\ti\pdk_C6678_1_1_2_6\packages" -"C:\ti\pdk_C6678_1_1_2_6\packages\ti\csl" \ No newline at end of file From 36471da716f85abe65c0415dce11c81730d64eff Mon Sep 17 00:00:00 2001 From: hdwei <1147479335@qq.com> Date: Thu, 27 Jan 2022 14:29:36 +0000 Subject: [PATCH 19/24] update bsp/ti-tms320c6678/README.md. --- bsp/ti-tms320c6678/README.md | 29 ++++++++++++++++++++++++----- 1 file changed, 24 insertions(+), 5 deletions(-) diff --git a/bsp/ti-tms320c6678/README.md b/bsp/ti-tms320c6678/README.md index ca8195b661..bdaae84265 100644 --- a/bsp/ti-tms320c6678/README.md +++ b/bsp/ti-tms320c6678/README.md @@ -1,13 +1,32 @@ -# 1.简介 +# 1. 简介 TMS320C6678是TI基于KeyStone的多核固定浮点数字信号处理器,DSP集成C66x CorePac,每个核心在1至1.25 GHz到10 GHz的运行。 该设备支持高性能的信号处理应用,如任务关键,医疗成像,测试和自动化。 -## 2.编译说明 +## 2. 编译说明 TMS320C6678 工程的编译和下载要使用的是 TI 官方提供的 Code Composer Studio。在本工程使用的是 CCS5.5 版本编译调试, CCS5.5 Compiler version:TIv8.3.5进行编译,需要安装TI提供的CSL库pdk_C6678_1_1_2_6。 -pdk_C6678_1_1_2_6安装路径为: -"C:\ti\pdk_C6678_1_1_2_6\packages" -"C:\ti\pdk_C6678_1_1_2_6\packages\ti\csl" +## 2.1 导入工程 + 首先打开 Code Composer Studio,点击 Project -> Import CCS Projects... +![输入图片说明](figures/import(1).png) + 在打开的对话框中,点击 Select search -> directory 右边的 Browse... 选择 TMS320C6678 BSP 所在文件夹,如图所示。选择完成后点击 Finish 完成导入。 +![输入图片说明](figures/import(2).png) +## 2.2 检查工程路径和编译器 + 检查工程路径是否正确,是否成功安装pdk_C6678_1_1_2_6,本工程安装路径为C盘。 +![输入图片说明](figures/filepath.png) + 检查编译器版本,本工程使用的是TIv8.3.5 +![输入图片说明](figures/general.jpg) + +## 3 编译工程 + 导入工程后,选中导入的 ti-tms320c6678 工程,右键点击,在弹出的菜单中选择 Build Project 即可开始编译。 + +## 4 加载和调试 + 编译完成后,可以开始加载和调试。将板子和 XDS560 仿真器连接,仿真器可以将编译生成的可执行文件加载到L2或MSMC执行。 + 如下图ti-tms320c6678.out是编译之后生成的可执行文件。 +![输入图片说明](figures/debug(1).png) + 本工程目前只支持单核运行,按如下图加载可执行文件。 +![输入图片说明](figures/load.png) + 加载可执行文件完成后,CCS将进入调试模式,可以选择继续运行、单步调试、复位等操作。 +![输入图片说明](figures/debug(2).png) \ No newline at end of file From 9fb11fd815379ed782273c06628f0f1ae648ece2 Mon Sep 17 00:00:00 2001 From: hdwei <1147479335@qq.com> Date: Thu, 27 Jan 2022 14:30:44 +0000 Subject: [PATCH 20/24] update bsp/ti-tms320c6678/README.md. --- bsp/ti-tms320c6678/README.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/bsp/ti-tms320c6678/README.md b/bsp/ti-tms320c6678/README.md index bdaae84265..ba9d16ecc5 100644 --- a/bsp/ti-tms320c6678/README.md +++ b/bsp/ti-tms320c6678/README.md @@ -8,25 +8,33 @@ CCS5.5 Compiler version:TIv8.3.5进行编译,需要安装TI提供的CSL库pdk_C6678_1_1_2_6。 ## 2.1 导入工程 + 首先打开 Code Composer Studio,点击 Project -> Import CCS Projects... ![输入图片说明](figures/import(1).png) + 在打开的对话框中,点击 Select search -> directory 右边的 Browse... 选择 TMS320C6678 BSP 所在文件夹,如图所示。选择完成后点击 Finish 完成导入。 ![输入图片说明](figures/import(2).png) ## 2.2 检查工程路径和编译器 + 检查工程路径是否正确,是否成功安装pdk_C6678_1_1_2_6,本工程安装路径为C盘。 ![输入图片说明](figures/filepath.png) + 检查编译器版本,本工程使用的是TIv8.3.5 ![输入图片说明](figures/general.jpg) ## 3 编译工程 + 导入工程后,选中导入的 ti-tms320c6678 工程,右键点击,在弹出的菜单中选择 Build Project 即可开始编译。 ## 4 加载和调试 + 编译完成后,可以开始加载和调试。将板子和 XDS560 仿真器连接,仿真器可以将编译生成的可执行文件加载到L2或MSMC执行。 如下图ti-tms320c6678.out是编译之后生成的可执行文件。 ![输入图片说明](figures/debug(1).png) + 本工程目前只支持单核运行,按如下图加载可执行文件。 ![输入图片说明](figures/load.png) + 加载可执行文件完成后,CCS将进入调试模式,可以选择继续运行、单步调试、复位等操作。 ![输入图片说明](figures/debug(2).png) \ No newline at end of file From 0ea04eb84215497f741dd42b50f05db0c2bb12e1 Mon Sep 17 00:00:00 2001 From: hdwei <1147479335@qq.com> Date: Thu, 27 Jan 2022 14:33:48 +0000 Subject: [PATCH 21/24] update bsp/ti-tms320c6678/README.md. --- bsp/ti-tms320c6678/README.md | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/bsp/ti-tms320c6678/README.md b/bsp/ti-tms320c6678/README.md index ba9d16ecc5..fb88f82626 100644 --- a/bsp/ti-tms320c6678/README.md +++ b/bsp/ti-tms320c6678/README.md @@ -1,11 +1,8 @@ - # 1. 简介 - TMS320C6678是TI基于KeyStone的多核固定浮点数字信号处理器,DSP集成C66x CorePac,每个核心在1至1.25 GHz到10 GHz的运行。 -该设备支持高性能的信号处理应用,如任务关键,医疗成像,测试和自动化。 + TMS320C6678是TI基于KeyStone的多核固定浮点数字信号处理器,DSP集成C66x CorePac,每个核心在1至1.25 GHz到10 GHz的运行。该设备支持高性能的信号处理应用,如任务关键,医疗成像,测试和自动化。 ## 2. 编译说明 - TMS320C6678 工程的编译和下载要使用的是 TI 官方提供的 Code Composer Studio。在本工程使用的是 CCS5.5 版本编译调试, -CCS5.5 Compiler version:TIv8.3.5进行编译,需要安装TI提供的CSL库pdk_C6678_1_1_2_6。 + TMS320C6678 工程的编译和下载要使用的是 TI 官方提供的 Code Composer Studio。在本工程使用的是 CCS5.5 版本编译调试,CCS5.5 Compiler version:TIv8.3.5进行编译,需要安装TI提供的CSL库pdk_C6678_1_1_2_6。 ## 2.1 导入工程 @@ -37,4 +34,6 @@ CCS5.5 Compiler version:TIv8.3.5进行编译,需要安装TI提供的CSL库pdk_ ![输入图片说明](figures/load.png) 加载可执行文件完成后,CCS将进入调试模式,可以选择继续运行、单步调试、复位等操作。 -![输入图片说明](figures/debug(2).png) \ No newline at end of file +![输入图片说明](figures/debug(2).png) + + 到此,可以开启tms320c6678 + rt-thread的愉快旅程了。 \ No newline at end of file From 5c8b4908e78dac292cf37e0d9e68391ad4e08a9f Mon Sep 17 00:00:00 2001 From: hdwei <1147479335@qq.com> Date: Thu, 27 Jan 2022 14:38:46 +0000 Subject: [PATCH 22/24] update bsp/ti-tms320c6678/README.md. --- bsp/ti-tms320c6678/README.md | 40 ++++++++++++++++++++---------------- 1 file changed, 22 insertions(+), 18 deletions(-) diff --git a/bsp/ti-tms320c6678/README.md b/bsp/ti-tms320c6678/README.md index fb88f82626..4ab913062b 100644 --- a/bsp/ti-tms320c6678/README.md +++ b/bsp/ti-tms320c6678/README.md @@ -1,39 +1,43 @@ -# 1. 简介 - TMS320C6678是TI基于KeyStone的多核固定浮点数字信号处理器,DSP集成C66x CorePac,每个核心在1至1.25 GHz到10 GHz的运行。该设备支持高性能的信号处理应用,如任务关键,医疗成像,测试和自动化。 +### 1. 简介 -## 2. 编译说明 - TMS320C6678 工程的编译和下载要使用的是 TI 官方提供的 Code Composer Studio。在本工程使用的是 CCS5.5 版本编译调试,CCS5.5 Compiler version:TIv8.3.5进行编译,需要安装TI提供的CSL库pdk_C6678_1_1_2_6。 +TMS320C6678是TI基于KeyStone的多核固定浮点数字信号处理器,DSP集成C66x CorePac,每个核心在1至1.25 GHz到10 GHz的运行。该设备支持高性能的信号处理应用,如任务关键,医疗成像,测试和自动化。 -## 2.1 导入工程 +### 2. 编译说明 - 首先打开 Code Composer Studio,点击 Project -> Import CCS Projects... +TMS320C6678 工程的编译和下载要使用的是 TI 官方提供的 Code Composer Studio。在本工程使用的是 CCS5.5 版本编译调试,CCS5.5 Compiler version:TIv8.3.5进行编译,需要安装TI提供的CSL库pdk_C6678_1_1_2_6。 + +### 2.1 导入工程 + +首先打开 Code Composer Studio,点击 Project -> Import CCS Projects... ![输入图片说明](figures/import(1).png) - 在打开的对话框中,点击 Select search -> directory 右边的 Browse... 选择 TMS320C6678 BSP 所在文件夹,如图所示。选择完成后点击 Finish 完成导入。 +在打开的对话框中,点击 Select search -> directory 右边的 Browse... 选择 TMS320C6678 BSP 所在文件夹,如图所示。选择完成后点击 Finish 完成导入。 ![输入图片说明](figures/import(2).png) -## 2.2 检查工程路径和编译器 +### 2.2 检查工程路径和编译器 - 检查工程路径是否正确,是否成功安装pdk_C6678_1_1_2_6,本工程安装路径为C盘。 +- 检查工程路径是否正确,是否成功安装pdk_C6678_1_1_2_6,本工程安装路径为C盘。 ![输入图片说明](figures/filepath.png) - 检查编译器版本,本工程使用的是TIv8.3.5 +- 检查编译器版本,本工程使用的是TIv8.3.5 + ![输入图片说明](figures/general.jpg) -## 3 编译工程 +### 3. 编译工程 - 导入工程后,选中导入的 ti-tms320c6678 工程,右键点击,在弹出的菜单中选择 Build Project 即可开始编译。 +导入工程后,选中导入的 ti-tms320c6678 工程,右键点击,在弹出的菜单中选择 Build Project 即可开始编译。 -## 4 加载和调试 +### 4. 加载和调试 - 编译完成后,可以开始加载和调试。将板子和 XDS560 仿真器连接,仿真器可以将编译生成的可执行文件加载到L2或MSMC执行。 - 如下图ti-tms320c6678.out是编译之后生成的可执行文件。 +编译完成后,可以开始加载和调试。将板子和 XDS560 仿真器连接,仿真器可以将编译生成的可执行文件加载到L2或MSMC执行。 + +- 如下图ti-tms320c6678.out是编译之后生成的可执行文件。 ![输入图片说明](figures/debug(1).png) - 本工程目前只支持单核运行,按如下图加载可执行文件。 +- 本工程目前只支持单核运行,按如下图加载可执行文件。 ![输入图片说明](figures/load.png) - 加载可执行文件完成后,CCS将进入调试模式,可以选择继续运行、单步调试、复位等操作。 +- 加载可执行文件完成后,CCS将进入调试模式,可以选择继续运行、单步调试、复位等操作。 ![输入图片说明](figures/debug(2).png) - 到此,可以开启tms320c6678 + rt-thread的愉快旅程了。 \ No newline at end of file + 到此,可以开启tms320c6678 + rt-thread的愉快旅程了 :smile: 。 \ No newline at end of file From 0d4e3a4b16d84a6e41ecb2eb2b4e32319c92d3be Mon Sep 17 00:00:00 2001 From: hdwei <1147479335@qq.com> Date: Thu, 27 Jan 2022 14:42:08 +0000 Subject: [PATCH 23/24] =?UTF-8?q?update=20bsp/ti-tms320c6678/README.md.=20?= =?UTF-8?q?=E6=B7=BB=E5=8A=A0READM.md=E8=AF=B4=E6=98=8E=E6=96=87=E6=A1=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- bsp/ti-tms320c6678/README.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/bsp/ti-tms320c6678/README.md b/bsp/ti-tms320c6678/README.md index 4ab913062b..7c6ffdf9e0 100644 --- a/bsp/ti-tms320c6678/README.md +++ b/bsp/ti-tms320c6678/README.md @@ -9,14 +9,17 @@ TMS320C6678 工程的编译和下载要使用的是 TI 官方提供的 Code Comp ### 2.1 导入工程 首先打开 Code Composer Studio,点击 Project -> Import CCS Projects... + ![输入图片说明](figures/import(1).png) 在打开的对话框中,点击 Select search -> directory 右边的 Browse... 选择 TMS320C6678 BSP 所在文件夹,如图所示。选择完成后点击 Finish 完成导入。 + ![输入图片说明](figures/import(2).png) ### 2.2 检查工程路径和编译器 - 检查工程路径是否正确,是否成功安装pdk_C6678_1_1_2_6,本工程安装路径为C盘。 + ![输入图片说明](figures/filepath.png) - 检查编译器版本,本工程使用的是TIv8.3.5 @@ -32,12 +35,15 @@ TMS320C6678 工程的编译和下载要使用的是 TI 官方提供的 Code Comp 编译完成后,可以开始加载和调试。将板子和 XDS560 仿真器连接,仿真器可以将编译生成的可执行文件加载到L2或MSMC执行。 - 如下图ti-tms320c6678.out是编译之后生成的可执行文件。 + ![输入图片说明](figures/debug(1).png) - 本工程目前只支持单核运行,按如下图加载可执行文件。 + ![输入图片说明](figures/load.png) - 加载可执行文件完成后,CCS将进入调试模式,可以选择继续运行、单步调试、复位等操作。 + ![输入图片说明](figures/debug(2).png) 到此,可以开启tms320c6678 + rt-thread的愉快旅程了 :smile: 。 \ No newline at end of file From c5ab5250bc7b0b57afa4bfd98aad818dd1889e66 Mon Sep 17 00:00:00 2001 From: hdwei <1147479335@qq.com> Date: Thu, 27 Jan 2022 14:43:52 +0000 Subject: [PATCH 24/24] update bsp/ti-tms320c6678/README.md. --- bsp/ti-tms320c6678/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bsp/ti-tms320c6678/README.md b/bsp/ti-tms320c6678/README.md index 7c6ffdf9e0..f78f4850bc 100644 --- a/bsp/ti-tms320c6678/README.md +++ b/bsp/ti-tms320c6678/README.md @@ -1,6 +1,6 @@ ### 1. 简介 -TMS320C6678是TI基于KeyStone的多核固定浮点数字信号处理器,DSP集成C66x CorePac,每个核心在1至1.25 GHz到10 GHz的运行。该设备支持高性能的信号处理应用,如任务关键,医疗成像,测试和自动化。 +TMS320C6678是TI基于KeyStone的多核固定浮点数字信号处理器,DSP集成C66x CorePac,每个核心在1GHz至1.25 GHz的运行。该设备支持高性能的信号处理应用,如任务关键,医疗成像,测试和自动化。 ### 2. 编译说明 @@ -46,4 +46,4 @@ TMS320C6678 工程的编译和下载要使用的是 TI 官方提供的 Code Comp ![输入图片说明](figures/debug(2).png) - 到此,可以开启tms320c6678 + rt-thread的愉快旅程了 :smile: 。 \ No newline at end of file +到此,可以开启tms320c6678 + rt-thread的愉快旅程了 :smile: 。 \ No newline at end of file