diff options
Diffstat (limited to 'libcpu/arm')
| -rw-r--r-- | libcpu/arm/am335x/SConscript | 17 | ||||
| -rw-r--r-- | libcpu/arm/am335x/am33xx.h | 333 | ||||
| -rw-r--r-- | libcpu/arm/am335x/context_gcc.S | 102 | ||||
| -rw-r--r-- | libcpu/arm/am335x/cp15_gcc.S | 145 | ||||
| -rw-r--r-- | libcpu/arm/am335x/cpu.c | 165 | ||||
| -rw-r--r-- | libcpu/arm/am335x/interrupt.c | 205 | ||||
| -rw-r--r-- | libcpu/arm/am335x/interrupt.h | 50 | ||||
| -rw-r--r-- | libcpu/arm/am335x/mmu.c | 457 | ||||
| -rw-r--r-- | libcpu/arm/am335x/stack.c | 65 | ||||
| -rw-r--r-- | libcpu/arm/am335x/start_gcc.S | 245 | ||||
| -rw-r--r-- | libcpu/arm/am335x/trap.c | 182 | ||||
| -rw-r--r-- | libcpu/arm/am335x/vector_gcc.S | 65 |
12 files changed, 2031 insertions, 0 deletions
diff --git a/libcpu/arm/am335x/SConscript b/libcpu/arm/am335x/SConscript new file mode 100644 index 0000000000..2ad51b573e --- /dev/null +++ b/libcpu/arm/am335x/SConscript @@ -0,0 +1,17 @@ +Import('rtconfig') +from building import * + +cwd = GetCurrentDir() +src = Glob('*.c') +CPPPATH = [cwd] + +if rtconfig.PLATFORM == 'iar': + src += Glob('*_iar.S') +elif rtconfig.PLATFORM == 'gcc': + src += Glob('*_gcc.S') +elif rtconfig.PLATFORM == 'armcc': + src += Glob('*_rvds.S') + +group = DefineGroup('AM1808', src, depend = [''], CPPPATH = CPPPATH) + +Return('group') diff --git a/libcpu/arm/am335x/am33xx.h b/libcpu/arm/am335x/am33xx.h new file mode 100644 index 0000000000..86ed82750a --- /dev/null +++ b/libcpu/arm/am335x/am33xx.h @@ -0,0 +1,333 @@ +#ifndef __AM33XX_H__ +#define __AM33XX_H__ + +#define REG32(x) (*((volatile unsigned int *)(x))) +#define REG16(x) (*((volatile unsigned short *)(x))) + +/** Cache Line size in ARM Cortex-A8. */ +#define AM33XX_CACHELINE_SIZE (64) + +/** @brief Base address of AINTC memory mapped registers */ +#define AM33XX_AINTC_REGS (0x48200000) + + +/** @brief Base addresses of control module registers */ +#define AM33XX_CTLM_REGS (0x44e10000) + +/** @brief Base addresses of USB memory mapped registers */ +#define AM33XX_USB_0_BASE (0x47401400) +#define AM33XX_USB_1_BASE (0x47401C00) +/** @brief Base addresses of SPI memory mapped registers */ +#define AM33XX_SPI_0_REGS (0x48030000) +#define AM33XX_SPI_1_REGS (0x481A0000) + +/** @brief Base addresses of GPIO memory mapped registers */ +#define AM33XX_GPIO_0_REGS (0x44E07000) +#define AM33XX_GPIO_1_REGS (0x4804C000) +#define AM33XX_GPIO_2_REGS (0x481AC000) +#define AM33XX_GPIO_3_REGS (0x481AE000) + +/** @brief Base addresses of DMTIMER memory mapped registers */ +#define AM33XX_DMTIMER_0_REGS (0x44E05000) +#define AM33XX_DMTIMER_1_REGS (0x44E31000) +#define AM33XX_DMTIMER_2_REGS (0x48040000) +#define AM33XX_DMTIMER_3_REGS (0x48042000) +#define AM33XX_DMTIMER_4_REGS (0x48044000) +#define AM33XX_DMTIMER_5_REGS (0x48046000) +#define AM33XX_DMTIMER_6_REGS (0x48048000) +#define AM33XX_DMTIMER_7_REGS (0x4804A000) + +/** @brief Base address of MMC memory mapped registers */ +#define AM33XX_MMCHS_0_REGS (0x48060000) +#define AM33XX_MMCHS_1_REGS (0x481D8000) +#define AM33XX_MMCHS_2_REGS (0x47810000) + +/** @brief Base address of GPMC memory mapped registers */ +#define AM33XX_GPMC_0_REGS (0x50000000) + +/** @brief Base address of GPMC memory mapped registers */ +#define AM33XX_ELM_0_REGS (0x48080000) + +/** @brief Base address of I2C memory mapped registers */ +#define AM33XX_I2C_0_REGS (0x44E0B000) +#define AM33XX_I2C_1_REGS (0x4802A000) +#define AM33XX_I2C_2_REGS (0x4819C000) + +/** @brief Base address of WDT memory mapped registers */ +#define AM33XX_WDT_0_REGS (0x44E33000) +#define AM33XX_WDT_1_REGS (0x44E35000) + +/** @brief Base address of WDT memory mapped registers */ +#define AM33XX_CPSW_SS_REGS (0x4A100000) +#define AM33XX_CPSW_MDIO_REGS (0x4A101000) +#define AM33XX_CPSW_WR_REGS (0x4A101200) +#define AM33XX_CPSW_CPDMA_REGS (0x4A100800) +#define AM33XX_CPSW_ALE_REGS (0x4A100D00) +#define AM33XX_CPSW_STAT_REGS (0x4A100900) +#define AM33XX_CPSW_PORT_0_REGS (0x4A100100) +#define AM33XX_CPSW_PORT_1_REGS (0x4A100200) +#define AM33XX_CPSW_SLIVER_1_REGS (0x4A100D80) +#define AM33XX_CPSW_PORT_2_REGS (0x4A100300) +#define AM33XX_CPSW_SLIVER_2_REGS (0x4A100DC0) +#define AM33XX_CPSW_CPPI_RAM_REGS (0x4A102000) + +/** @brief Base address of McASP memory mapped registers */ +#define AM33XX_MCASP_1_CTRL_REGS (0x4803C000) +#define AM33XX_MCASP_1_FIFO_REGS (AM33XX_MCASP_1_CTRL_REGS + 0x1000) +#define AM33XX_MCASP_1_DATA_REGS (0x46400000) + +/** @brief Base address of EMIF memory mapped registers */ +#define AM33XX_EMIF_0_REGS (0x4C000000) + +/** @brief Base addresses of RTC memory mapped registers */ +#define AM33XX_RTC_0_REGS (0x44E3E000) + +#define CM_PER(base) ((base) + 0) +#define CM_PER_L4LS_CLKSTCTRL(base) (CM_PER(base) + 0) +#define CM_PER_UART1_CLKCTRL(base) (CM_PER(base) + 0x06C) +#define CM_WKUP(base) ((base) + 0x400) +#define CM_DPLL(base) ((base) + 0x500) +#define CM_MPU(base) ((base) + 0x600) +#define CM_DEVICE(base) ((base) + 0x700) +#define CM_RTC(base) ((base) + 0x800) +#define CM_GFX(base) ((base) + 0x900) +#define CM_CEFUSE(base) ((base) + 0xA00) +#define OCP_AM33XXKET_RAM(base) ((base) + 0xB00) +#define PRM_PER(base) ((base) + 0xC00) +#define PRM_PER_PWRSTST(base) (PRM_PER(base) + 0x008) +#define PRM_PER_PWRSTCTRL(base) (PRM_PER(base) + 0x00C) +#define PRM_WKUP(base) ((base) + 0xD00) +#define PRM_MPU(base) ((base) + 0xE00) +#define PRM_DEVICE(base) ((base) + 0xF00) +#define PRM_RTC(base) ((base) + 0x1000) +#define PRM_GFX(base) ((base) + 0x1100) +#define PRM_CEFUSE(base) ((base) + 0x1200) + +/** @brief Base addresses of PRCM memory mapped registers */ +#define AM33XX_PRCM_REGS (0x44E00000) +#define AM33XX_CM_PER_REGS CM_PER(AM33XX_PRCM_REGS) +#define AM33XX_CM_WKUP_REGS CM_WKUP(AM33XX_PRCM_REGS) +#define AM33XX_CM_DPLL_REGS CM_DPLL(AM33XX_PRCM_REGS) +#define AM33XX_CM_MPU_REGS CM_MPU(AM33XX_PRCM_REGS) +#define AM33XX_CM_DEVICE_REGS CM_DEVICE(AM33XX_PRCM_REGS) +#define AM33XX_CM_RTC_REGS CM_RTC(AM33XX_PRCM_REGS) +#define AM33XX_CM_GFX_REGS CM_GFX(AM33XX_PRCM_REGS) +#define AM33XX_CM_CEFUSE_REGS CM_CEFUSE(AM33XX_PRCM_REGS) +#define AM33XX_OCP_AM33XXKET_RAM_REGS OCP_AM33XXKET_RAM(AM33XX_PRCM_REGS) +#define AM33XX_PRM_PER_REGS PRM_PER(AM33XX_PRCM_REGS) +#define AM33XX_PRM_WKUP_REGS PRM_WKUP(AM33XX_PRCM_REGS) +#define AM33XX_PRM_MPU_REGS PRM_MPU(AM33XX_PRCM_REGS) +#define AM33XX_PRM_DEVICE_REGS PRM_DEVICE(AM33XX_PRCM_REGS) +#define AM33XX_PRM_RTC_REGS PRM_RTC(AM33XX_PRCM_REGS) +#define AM33XX_PRM_GFX_REGS PRM_GFX(AM33XX_PRCM_REGS) +#define AM33XX_PRM_CEFUSE_REGS PRM_CEFUSE(AM33XX_PRCM_REGS) + +/** @brief Base address of control module memory mapped registers */ +#define AM33XX_CONTROL_REGS (0x44E10000) + + +/** @brief Base address of Channel controller memory mapped registers */ +#define AM33XX_EDMA30CC_0_REGS (0x49000000) + +/** @brief Base address of DCAN module memory mapped registers */ +#define AM33XX_DCAN_0_REGS (0x481CC000) +#define AM33XX_DCAN_1_REGS (0x481D0000) + +/******************************************************************************\ +* Parameterizable Configuration:- These are fed directly from the RTL +* parameters for the given AM33XX +\******************************************************************************/ +#define TPCC_MUX(n) 0xF90 + ((n) * 4) + + +#define AM33XX_LCDC_0_REGS 0x4830E000 + +#define AM33XX_ADC_TSC_0_REGS 0x44E0D000 + +/** @brief Base addresses of PWMSS memory mapped registers. */ + +#define AM33XX_PWMSS0_REGS (0x48300000) +#define AM33XX_PWMSS1_REGS (0x48302000) +#define AM33XX_PWMSS2_REGS (0x48304000) + +#define AM33XX_ECAP_REGS (0x00000100) +#define AM33XX_EQEP_REGS (0x00000180) +#define AM33XX_EPWM_REGS (0x00000200) + +#define AM33XX_ECAP_0_REGS (AM33XX_PWMSS0_REGS + AM33XX_ECAP_REGS) +#define AM33XX_ECAP_1_REGS (AM33XX_PWMSS1_REGS + AM33XX_ECAP_REGS) +#define AM33XX_ECAP_2_REGS (AM33XX_PWMSS2_REGS + AM33XX_ECAP_REGS) + +#define AM33XX_EQEP_0_REGS (AM33XX_PWMSS0_REGS + AM33XX_EQEP_REGS) +#define AM33XX_EQEP_1_REGS (AM33XX_PWMSS1_REGS + AM33XX_EQEP_REGS) +#define AM33XX_EQEP_2_REGS (AM33XX_PWMSS2_REGS + AM33XX_EQEP_REGS) + +#define AM33XX_EPWM_0_REGS (AM33XX_PWMSS0_REGS + AM33XX_EPWM_REGS) +#define AM33XX_EPWM_1_REGS (AM33XX_PWMSS1_REGS + AM33XX_EPWM_REGS) +#define AM33XX_EPWM_2_REGS (AM33XX_PWMSS2_REGS + AM33XX_EPWM_REGS) + +#define AM33XX_EPWM_MODULE_FREQ 100 + +/* PRCM registers */ +#define CM_PER_L4LS_CLKSTCTRL_REG(base) REG32((base) + 0x0) +#define CM_PER_UART1_CLKCTRL_REG(base) REG32(CM_PER_UART1_CLKCTRL(base)) + +#define CM_PER_TIMER7_CLKCTRL(base) REG32((base) + 0x7C) +#define CM_PER_TIMER2_CLKCTRL(base) REG32((base) + 0x80) + +#define PRM_PER_PWRSTST_REG(base) REG32(PRM_PER_PWRSTST(base)) +#define PRM_PER_PWRSTCTRL_REG(base) REG32(PRM_PER_PWRSTCTRL(base)) + +#define CM_DPLL_CLKSEL_TIMER7_CLK(base) REG32(CM_DPLL(base) + 0x4) +#define CM_DPLL_CLKSEL_TIMER2_CLK(base) REG32(CM_DPLL(base) + 0x8) + +/* timer registers */ +#define DMTIMER_TIDR(base) REG32(base + 0x0) +#define DMTIMER_TIOCP_CFG(base) REG32(base + 0x10) +#define DMTIMER_IRQ_EOI(base) REG32(base + 0x20) +#define DMTIMER_IRQSTATUS_RAW(base) REG32(base + 0x24) +#define DMTIMER_IRQSTATUS(base) REG32(base + 0x28) +#define DMTIMER_IRQENABLE_SET(base) REG32(base + 0x2C) +#define DMTIMER_IRQENABLE_CLR(base) REG32(base + 0x30) +#define DMTIMER_IRQWAKEEN(base) REG32(base + 0x34) +#define DMTIMER_TCLR(base) REG32(base + 0x38) +#define DMTIMER_TCRR(base) REG32(base + 0x3C) +#define DMTIMER_TLDR(base) REG32(base + 0x40) +#define DMTIMER_TTGR(base) REG32(base + 0x44) +#define DMTIMER_TWPS(base) REG32(base + 0x48) +#define DMTIMER_TMAR(base) REG32(base + 0x4C) +#define DMTIMER_TCAR(base, n) REG32(base + 0x50 + (((n) - 1) * 8)) +#define DMTIMER_TSICR(base) REG32(base + 0x54) + +#define EMU_INT 0 +#define COMMTX_INT 1 +#define COMMRX_INT 2 +#define BENCH_INT 3 +#define ELM_IRQ_INT 4 +#define NMI_INT 7 +#define L3DEBUG_INT 9 +#define L3APP_INT 10 +#define PRCM_INT 11 +#define EDMACOMP_INT 12 +#define EDMAMPERR_INT 13 +#define EDMAERR_INT 14 +#define ADC_TSC_GEN_INT 16 +#define USBSS_INT 17 +#define USB_INT0 18 +#define USB_INT1 19 +#define PRU_ICSS_EVTOUT0_INT 20 +#define PRU_ICSS_EVTOUT1_INT 21 +#define PRU_ICSS_EVTOUT2_INT 22 +#define PRU_ICSS_EVTOUT3_INT 23 +#define PRU_ICSS_EVTOUT4_INT 24 +#define PRU_ICSS_EVTOUT5_INT 25 +#define PRU_ICSS_EVTOUT6_INT 26 +#define PRU_ICSS_EVTOUT7_INT 27 +#define MMCSD1_INT 28 +#define MMCSD2_INT 29 +#define I2C2_INT 30 +#define ECAP0_INT 31 +#define GPIO_INT2A 32 +#define GPIO_INT2B 33 +#define USBWAKEUP_INT 34 +#define LCDC_INT 36 +#define GFX_INT 37 +#define EPWM2_INT 39 +#define CPSW_RXTHR0_INT 40 +#define CPSW_RX_INT0 41 +#define CPSW_TX_INT0 42 +#define CPSW_MISC0_INT 43 +#define UART3_INT 44 +#define UART4_INT 45 +#define UART5_INT 46 +#define ECAP1_INT 47 +#define DCAN0_INT0 52 +#define DCAN0_INT1 53 +#define DCAN0_PARITY 54 +#define DCAN1_INT0 55 +#define DCAN1_INT1 56 +#define DCAN1_PARITY 57 +#define EPWM0_TZINT 58 +#define EPWM1_TZINT 59 +#define EPWM2_TZINT 60 +#define ECAP2_INT 61 +#define GPIO_INT3A 62 +#define GPIO_INT3B 63 +#define MMCSD0_INT 64 +#define MCSPI0_INT 65 +#define TINT0 66 +#define TINT1_1MS 67 +#define TINT2 68 +#define TINT3 69 +#define I2C0_INT 70 +#define I2C1_INT 71 +#define UART0_INT 72 +#define UART1_INT 73 +#define UART2_INT 74 +#define RTC_INT 75 +#define RTC_ALARM_INT 76 +#define MB_INT0 77 +#define M3_TXEV 78 +#define EQEP0_INT 79 +#define MACTX_INT0 80 +#define MCARX_INT0 81 +#define MCATX_INT1 82 +#define MCARX_INT1 83 +#define EPWM0_INT 86 +#define EPWM1_INT 87 +#define EQEP1_INT 88 +#define EQEP2_INT 89 +#define DMA_INTR_PIN2 90 +#define WDT1_INT 91 +#define TINT4 92 +#define TINT5 93 +#define TINT6 94 +#define TINT7 95 +#define GPIO_INT0A 96 +#define GPIO_INT0B 97 +#define GPIO_INT1A 98 +#define GPIO_INT1B 99 +#define GPMC_INT 100 +#define DDRERR0 101 +#define TCERR_INT0 112 +#define TCERR_INT1 113 +#define TCERR_INT2 114 +#define ADC_TSC_PEN_INT 115 +#define SMRFLX_MPU 120 +#define SMRFLX_CORE 121 +#define DMA_INTR_PIN0 123 +#define DMA_INTR_PIN1 124 +#define MCSPI1_INT 125 + +struct rt_hw_register +{ + unsigned long r0; + unsigned long r1; + unsigned long r2; + unsigned long r3; + unsigned long r4; + unsigned long r5; + unsigned long r6; + unsigned long r7; + unsigned long r8; + unsigned long r9; + unsigned long r10; + unsigned long fp; + unsigned long ip; + unsigned long sp; + unsigned long lr; + unsigned long pc; + unsigned long cpsr; + unsigned long ORIG_r0; +}; + +#define USERMODE 0x10 +#define FIQMODE 0x11 +#define IRQMODE 0x12 +#define SVCMODE 0x13 +#define ABORTMODE 0x17 +#define UNDEFMODE 0x1b +#define MODEMASK 0x1f +#define NOINT 0xc0 + +#endif diff --git a/libcpu/arm/am335x/context_gcc.S b/libcpu/arm/am335x/context_gcc.S new file mode 100644 index 0000000000..a49ce0862d --- /dev/null +++ b/libcpu/arm/am335x/context_gcc.S @@ -0,0 +1,102 @@ +/* + * File : context.S + * This file is part of RT-Thread RTOS + * COPYRIGHT (C) 2013, RT-Thread Development Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Change Logs: + * Date Author Notes + * 2013-07-05 Bernard the first version + */ + +/* + * rt_base_t rt_hw_interrupt_disable(); + */ +.globl rt_hw_interrupt_disable +rt_hw_interrupt_disable: + mrs r0, cpsr + cpsid if + bx lr + +/* + * void rt_hw_interrupt_enable(rt_base_t level); + */ +.globl rt_hw_interrupt_enable +rt_hw_interrupt_enable: + msr cpsr_c, r0 + bx lr + +/* + * void rt_hw_context_switch(rt_uint32 from, rt_uint32 to); + * r0 --> from + * r1 --> to + */ +.globl rt_hw_context_switch +rt_hw_context_switch: + stmfd sp!, {lr} @ push pc (lr should be pushed in place of PC) + stmfd sp!, {r0-r12, lr} @ push lr & register file + + mrs r4, cpsr + tst lr, #0x01 + orrne r4, r4, #0x20 @ it's thumb code + + stmfd sp!, {r4} @ push cpsr + + str sp, [r0] @ store sp in preempted tasks TCB + ldr sp, [r1] @ get new task stack pointer + + ldmfd sp!, {r4} @ pop new task cpsr to spsr + msr spsr_cxsf, r4 + +_do_switch: + ldmfd sp!, {r0-r12, lr, pc}^ @ pop new task r0-r12, lr & pc, copy spsr to cpsr + +/* + * void rt_hw_context_switch_to(rt_uint32 to); + * r0 --> to + */ +.globl rt_hw_context_switch_to +rt_hw_context_switch_to: + ldr sp, [r0] @ get new task stack pointer + + ldmfd sp!, {r4} @ pop new task spsr + msr spsr_cxsf, r4 + + bic r4, r4, #0x20 @ must be ARM mode + msr cpsr_cxsf, r4 + + ldmfd sp!, {r0-r12, lr, pc}^ @ pop new task r0-r12, lr & pc + +/* + * void rt_hw_context_switch_interrupt(rt_uint32 from, rt_uint32 to); + */ +.globl rt_thread_switch_interrupt_flag +.globl rt_interrupt_from_thread +.globl rt_interrupt_to_thread +.globl rt_hw_context_switch_interrupt +rt_hw_context_switch_interrupt: + ldr r2, =rt_thread_switch_interrupt_flag + ldr r3, [r2] + cmp r3, #1 + beq _reswitch + mov r3, #1 @ set rt_thread_switch_interrupt_flag to 1 + str r3, [r2] + ldr r2, =rt_interrupt_from_thread @ set rt_interrupt_from_thread + str r0, [r2] +_reswitch: + ldr r2, =rt_interrupt_to_thread @ set rt_interrupt_to_thread + str r1, [r2] + bx lr diff --git a/libcpu/arm/am335x/cp15_gcc.S b/libcpu/arm/am335x/cp15_gcc.S new file mode 100644 index 0000000000..1f8e685e21 --- /dev/null +++ b/libcpu/arm/am335x/cp15_gcc.S @@ -0,0 +1,145 @@ +/* + * File : cp15_gcc.S + * This file is part of RT-Thread RTOS + * COPYRIGHT (C) 2013, RT-Thread Development Team + * http://www.rt-thread.org + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Change Logs: + * Date Author Notes + * 2013-07-05 Bernard the first version + */ + +.globl rt_cpu_vector_set_base +rt_cpu_vector_set_base: + mcr p15, #0, r0, c12, c0, #0 + dsb + bx lr + +.globl rt_cpu_vector_get_base +rt_cpu_vector_get_base: + mrc p15, #0, r0, c12, c0, #0 + bx lr + +.globl rt_cpu_get_sctlr +rt_cpu_get_sctlr: + mrc p15, #0, r0, c1, c0, #0 + bx lr + +.globl rt_cpu_dcache_enable +rt_cpu_dcache_enable: + mrc p15, #0, r0, c1, c0, #0 + orr r0, r0, #0x00000004 + mcr p15, #0, r0, c1, c0, #0 + bx lr + +.globl rt_cpu_icache_enable +rt_cpu_icache_enable: + mrc p15, #0, r0, c1, c0, #0 + orr r0, r0, #0x00001000 + mcr p15, #0, r0, c1, c0, #0 + bx lr + +_FLD_MAX_WAY: + .word 0x3ff +_FLD_MAX_IDX: + .word 0x7ff + +.globl rt_cpu_dcache_clean_flush +rt_cpu_dcache_clean_flush: + push {r4-r11} + dmb + mrc p15, #1, r0, c0, c0, #1 @ read clid register + ands r3, r0, #0x7000000 @ get level of coherency + mov r3, r3, lsr #23 + beq finished + mov r10, #0 +loop1: + add r2, r10, r10, lsr #1 + mov r1, r0, lsr r2 + and r1, r1, #7 + cmp r1, #2 + blt skip + mcr p15, #2, r10, c0, c0, #0 + isb + mrc p15, #1, r1, c0, c0, #0 + and r2, r1, #7 + add r2, r2, #4 + ldr r4, _FLD_MAX_WAY + ands r4, r4, r1, lsr #3 + clz r5, r4 + ldr r7, _FLD_MAX_IDX + ands r7, r7, r1, lsr #13 +loop2: + mov r9, r4 +loop3: + orr r11, r10, r9, lsl r5 + orr r11, r11, r7, lsl r2 + mcr p15, #0, r11, c7, c14, #2 + subs r9, r9, #1 + bge loop3 + subs r7, r7, #1 + bge loop2 +skip: + add r10, r10, #2 + cmp r3, r10 + bgt loop1 + +finished: + dsb + isb + pop {r4-r11} + bx lr + +.globl rt_cpu_dcache_disable +rt_cpu_dcache_disable: + push {r4-r11, lr} + mrc p15, #0, r0, c1, c0, #0 + bic r0, r0, #0x00000004 + mcr p15, #0, r0, c1, c0, #0 + bl rt_cpu_dcache_clean_flush + pop {r4-r11, lr} + bx lr + +.globl rt_cpu_icache_disable +rt_cpu_icache_disable: + mrc p15, #0, r0, c1, c0, #0 + bic r0, r0, #0x00001000 + mcr p15, #0, r0, c1, c0, #0 + bx lr + +.globl rt_cpu_mmu_disable +rt_cpu_mmu_disable: + mcr p15, #0, r0, c8, c7, #0 @ invalidate tlb + mrc p15, #0, r0, c1, c0, #0 + bic r0, r0, #1 + mcr p15, #0, r0, c1, c0, #0 @ clear mmu bit + dsb + bx lr + +.globl rt_cpu_mmu_enable +rt_cpu_mmu_enable: + mrc p15, #0, r0, c1, c0, #0 + orr r0, r0, #0x001 + mcr p15, #0, r0, c1, c0, #0 @ set mmu enable bit + dsb + bx lr + +.globl rt_cpu_tlb_set +rt_cpu_tlb_set: + mcr p15, #0, r0, c2, c0, #0 + dmb + bx lr diff --git a/libcpu/arm/am335x/cpu.c b/libcpu/arm/am335x/cpu.c new file mode 100644 index 0000000000..e67983eed0 --- /dev/null +++ b/libcpu/arm/am335x/cpu.c @@ -0,0 +1,165 @@ +/* + * File : cpu.c + * This file is part of RT-Thread RTOS + * COPYRIGHT (C) 2006, RT-Thread Develop Team + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rt-thread.org/license/LICENSE + * + * Change Logs: + * Date Author Notes + * 2011-09-15 Bernard first version + */ + +#include <rthw.h> +#include <rtthread.h> +#include "am33xx.h" + +/** + * @addtogroup AM33xx + */ +/*@{*/ + +#define ICACHE_MASK (rt_uint32_t)(1 << 12) +#define DCACHE_MASK (rt_uint32_t)(1 << 2) + +#if defined(__CC_ARM) +rt_inline rt_uint32_t cp15_rd(void) +{ + rt_uint32_t i; + + __asm + { + mrc p15, 0, i, c1, c0, 0 + } + + return i; +} + +rt_inline void cache_enable(rt_uint32_t bit) +{ + rt_uint32_t value; + + __asm + { + mrc p15, 0, value, c1, c0, 0 + orr value, value, bit + mcr p15, 0, value, c1, c0, 0 + } +} + +rt_inline void cache_disable(rt_uint32_t bit) +{ + rt_uint32_t value; + + __asm + { + mrc p15, 0, value, c1, c0, 0 + bic value, value, bit + mcr p15, 0, value, c1, c0, 0 + } +} +#elif defined(__GNUC__) +rt_inline rt_uint32_t cp15_rd(void) +{ + rt_uint32_t i; + + asm ("mrc p15, 0, %0, c1, c0, 0":"=r" (i)); + return i; +} + +rt_inline void cache_enable(rt_uint32_t bit) +{ + __asm__ __volatile__( \ + "mrc p15,0,r0,c1,c0,0\n\t" \ + "orr r0,r0,%0\n\t" \ + "mcr p15,0,r0,c1,c0,0" \ + : \ + :"r" (bit) \ + :"memory"); +} + +rt_inline void cache_disable(rt_uint32_t bit) +{ + __asm__ __volatile__( \ + "mrc p15,0,r0,c1,c0,0\n\t" \ + "bic r0,r0,%0\n\t" \ + "mcr p15,0,r0,c1,c0,0" \ + : \ + :"r" (bit) \ + :"memory"); +} +#endif + +/** + * enable I-Cache + * + */ +void rt_hw_cpu_icache_enable() +{ + cache_enable(ICACHE_MASK); +} + +/** + * disable I-Cache + * + */ +void rt_hw_cpu_icache_disable() +{ + cache_disable(ICACHE_MASK); +} + +/** + * return the status of I-Cache + * + */ +rt_base_t rt_hw_cpu_icache_status() +{ + return (cp15_rd() & ICACHE_MASK); +} + +/** + * enable D-Cache + * + */ +void rt_hw_cpu_dcache_enable() +{ + cache_enable(DCACHE_MASK); +} + +/** + * disable D-Cache + * + */ +void rt_hw_cpu_dcache_disable() +{ + cache_disable(DCACHE_MASK); +} + +/** + * return the status of D-Cache + * + */ +rt_base_t rt_hw_cpu_dcache_status() +{ + return (cp15_rd() & DCACHE_MASK); +} + +/** + * shutdown CPU + * + */ +void rt_hw_cpu_shutdown() +{ + rt_uint32_t level; + rt_kprintf("shutdown...\n"); + + level = rt_hw_interrupt_disable(); + while (level) + { + RT_ASSERT(0); + } +} + +/*@}*/ diff --git a/libcpu/arm/am335x/interrupt.c b/libcpu/arm/am335x/interrupt.c new file mode 100644 index 0000000000..081bdd6b41 --- /dev/null +++ b/libcpu/arm/am335x/interrupt.c @@ -0,0 +1,205 @@ +/* + * File : interrupt.c + * This file is part of RT-Thread RTOS + * COPYRIGHT (C) 2011, RT-Thread Development Team + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rt-thread.org/license/LICENSE + * + * Change Logs: + * Date Author Notes + * 2013-07-06 Bernard first version + */ + +#include <rthw.h> +#include <rtthread.h> + +#include "am33xx.h" +#include "interrupt.h" + +#define AINTC_BASE AM33XX_AINTC_REGS + +#define MAX_HANDLERS 128 + +extern volatile rt_uint8_t rt_interrupt_nest; + +/* exception and interrupt handler table */ +struct rt_irq_desc isr_table[MAX_HANDLERS]; +rt_uint32_t rt_interrupt_from_thread, rt_interrupt_to_thread; +rt_uint32_t rt_thread_switch_interrupt_flag; + +/** + * @addtogroup AM33xx + */ +/*@{*/ + +void rt_dump_aintc(void) +{ + int k; + rt_kprintf("active irq %d", INTC_SIR_IRQ(AINTC_BASE)); + rt_kprintf("\n--- hw mask ---\n"); + for (k = 0; k < 4; k++) + { + rt_kprintf("0x%08x, ", INTC_MIR(AINTC_BASE, k)); + } + rt_kprintf("\n--- hw itr ---\n"); + for (k = 0; k < 4; k++) + { + rt_kprintf("0x%08x, ", INTC_ITR(AINTC_BASE, k)); + } + rt_kprintf("\n"); +} + +const unsigned int AM335X_VECTOR_BASE = 0x4030FC00; +extern void rt_cpu_vector_set_base(unsigned int addr); +extern int system_vectors; + +static void rt_hw_vector_init(void) +{ + unsigned int *dest = (unsigned int *)AM335X_VECTOR_BASE; + unsigned int *src = (unsigned int *)&system_vectors; + + rt_memcpy(dest, src, 16 * 4); + rt_cpu_vector_set_base(AM335X_VECTOR_BASE); +} + +/** + * This function will initialize hardware interrupt + */ +void rt_hw_interrupt_init(void) +{ + /* initialize vector table */ + rt_hw_vector_init(); + + /* 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) +{ + INTC_MIR_SET(AINTC_BASE, vector >> 0x05) = 0x1 << (vector & 0x1f); +} + +/** + * This function will un-mask a interrupt. + * @param vector the interrupt number + */ +void rt_hw_interrupt_umask(int vector) +{ + INTC_MIR_CLEAR(AINTC_BASE, vector >> 0x05) = 0x1 << (vector & 0x1f); +} + +/** + * This function will control the interrupt attribute. + * @param vector the interrupt number + */ +void rt_hw_interrupt_control(int vector, int priority, int route) +{ + int fiq; + + if (route == 0) + fiq = 0; + else + fiq = 1; + + INTC_ILR(AINTC_BASE, vector) = ((priority << 0x02) & 0x1FC) | fiq ; +} + +int rt_hw_interrupt_get_active(int fiq_irq) +{ + int ir; + if (fiq_irq == INT_FIQ) + { + ir = INTC_SIR_FIQ(AINTC_BASE) & 0x7f; + } + else + { + ir = INTC_SIR_IRQ(AINTC_BASE) & 0x7f; + } + + return ir; +} + +void rt_hw_interrupt_ack(int fiq_irq) +{ + if (fiq_irq == INT_FIQ) + { + /* new FIQ generation */ + INTC_CONTROL(AINTC_BASE) |= 0x02; + } + else + { + /* new IRQ generation */ + INTC_CONTROL(AINTC_BASE) |= 0x01; + } +} + +/** + * 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, char *name) +{ + rt_isr_handler_t old_handler = RT_NULL; + + if(vector < MAX_HANDLERS) + { + 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; +} + +/** + * This function will trigger an interrupt. + * @param vector the interrupt number + */ +void rt_hw_interrupt_trigger(int vector) +{ + INTC_ISR_SET(AINTC_BASE, vector>>5) = 1 << (vector & 0x1f); +} + +void rt_hw_interrupt_clear(int vector) +{ + INTC_ISR_CLEAR(AINTC_BASE, vector>>5) = 1 << (vector & 0x1f); +} + +void rt_dump_isr_table(void) +{ + int idx; + for(idx = 0; idx < MAX_HANDLERS; idx++) + { +#ifdef RT_USING_INTERRUPT_INFO + rt_kprintf("nr:%4d, name: %*.s, handler: 0x%p, param: 0x%08x\r\n", + idx, RT_NAME_MAX, isr_table[idx].name, + isr_table[idx].handler, isr_table[idx].param); +#else + rt_kprintf("nr:%4d, handler: 0x%p, param: 0x%08x\r\n", + idx, isr_table[idx].handler, isr_table[idx].param); +#endif + } +} +/*@}*/ diff --git a/libcpu/arm/am335x/interrupt.h b/libcpu/arm/am335x/interrupt.h new file mode 100644 index 0000000000..d81f1c81ae --- /dev/null +++ b/libcpu/arm/am335x/interrupt.h @@ -0,0 +1,50 @@ +/* + * File : interrupt.h + * This file is part of RT-Thread RTOS + * COPYRIGHT (C) 2011, RT-Thread Development Team + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rt-thread.org/license/LICENSE + * + * Change Logs: + * Date Author Notes + * 2013-07-06 Bernard first version + */ + +#ifndef __INTERRUPT_H__ +#define __INTERRUPT_H__ + +#define INT_IRQ 0x00 +#define INT_FIQ 0x01 + +#define INTC_REVISION(hw_base) REG32((hw_base) + 0x0) +#define INTC_SYSCONFIG(hw_base) REG32((hw_base) + 0x10) +#define INTC_SYSSTATUS(hw_base) REG32((hw_base) + 0x14) +#define INTC_SIR_IRQ(hw_base) REG32((hw_base) + 0x40) +#define INTC_SIR_FIQ(hw_base) REG32((hw_base) + 0x44) +#define INTC_CONTROL(hw_base) REG32((hw_base) + 0x48) +#define INTC_PROTECTION(hw_base) REG32((hw_base) + 0x4c) +#define INTC_IDLE(hw_base) REG32((hw_base) + 0x50) +#define INTC_IRQ_PRIORITY(hw_base) REG32((hw_base) + 0x60) +#define INTC_FIQ_PRIORITY(hw_base) REG32((hw_base) + 0x64) +#define INTC_THRESHOLD(hw_base) REG32((hw_base) + 0x68) +#define INTC_SICR(hw_base) REG32((hw_base) + 0x6c) +#define INTC_SCR(hw_base, n) REG32((hw_base) + 0x70 + ((n) * 0x04)) +#define INTC_ITR(hw_base, n) REG32((hw_base) + 0x80 + ((n) * 0x20)) +#define INTC_MIR(hw_base, n) REG32((hw_base) + 0x84 + ((n) * 0x20)) +#define INTC_MIR_CLEAR(hw_base, n) REG32((hw_base) + 0x88 + ((n) * 0x20)) +#define INTC_MIR_SET(hw_base, n) REG32((hw_base) + 0x8c + ((n) * 0x20)) +#define INTC_ISR_SET(hw_base, n) REG32((hw_base) + 0x90 + ((n) * 0x20)) +#define INTC_ISR_CLEAR(hw_base, n) REG32((hw_base) + 0x94 + ((n) * 0x20)) +#define INTC_PENDING_IRQ(hw_base, n) REG32((hw_base) + 0x98 + ((n) * 0x20)) +#define INTC_PENDING_FIQ(hw_base, n) REG32((hw_base) + 0x9c + ((n) * 0x20)) +#define INTC_ILR(hw_base, n) REG32((hw_base) + 0x100 + ((n) * 0x04)) + +void rt_hw_interrupt_control(int vector, int priority, int route); +int rt_hw_interrupt_get_active(int fiq_irq); +void rt_hw_interrupt_ack(int fiq_irq); +void rt_hw_interrupt_trigger(int vector); +void rt_hw_interrupt_clear(int vector); + +#endif diff --git a/libcpu/arm/am335x/mmu.c b/libcpu/arm/am335x/mmu.c new file mode 100644 index 0000000000..46f2d6afd7 --- /dev/null +++ b/libcpu/arm/am335x/mmu.c @@ -0,0 +1,457 @@ +/* + * File : mmu.c + * This file is part of RT-Thread RTOS + * COPYRIGHT (C) 2006, RT-Thread Development Team + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rt-thread.org/license/LICENSE + * + * Change Logs: + * Date Author Notes + * 2012-01-10 bernard porting to AM1808 + */ + +#include <rtthread.h> +#include "am33xx.h" + +#define DESC_SEC (0x2|(1<<4)) +#define CB (3<<2) //cache_on, write_back +#define CNB (2<<2) //cache_on, write_through +#define NCB (1<<2) //cache_off,WR_BUF on +#define NCNB (0<<2) //cache_off,WR_BUF off +#define AP_RW (3<<10) //supervisor=RW, user=RW +#define AP_RO (2<<10) //supervisor=RW, user=RO + +#define DOMAIN_FAULT (0x0) +#define DOMAIN_CHK (0x1) +#define DOMAIN_NOTCHK (0x3) +#define DOMAIN0 (0x0<<5) +#define DOMAIN1 (0x1<<5) + +#define DOMAIN0_ATTR (DOMAIN_CHK<<0) +#define DOMAIN1_ATTR (DOMAIN_FAULT<<2) + +#define RW_CB (AP_RW|DOMAIN0|CB|DESC_SEC) /* Read/Write, cache, write back */ +#define RW_CNB (AP_RW|DOMAIN0|CNB|DESC_SEC) /* Read/Write, cache, write through */ +#define RW_NCNB (AP_RW|DOMAIN0|NCNB|DESC_SEC) /* Read/Write without cache and write buffer */ +#define RW_FAULT (AP_RW|DOMAIN1|NCNB|DESC_SEC) /* Read/Write without cache and write buffer */ + +#ifdef __CC_ARM +void mmu_setttbase(rt_uint32_t i) +{ + register rt_uint32_t value; + + /* Invalidates all TLBs.Domain access is selected as + * client by configuring domain access register, + * in that case access controlled by permission value + * set by page table entry + */ + value = 0; + __asm + { + mcr p15, 0, value, c8, c7, 0 + } + + value = 0x55555555; + __asm + { + mcr p15, 0, value, c3, c0, 0 + mcr p15, 0, i, c2, c0, 0 + } +} + +void mmu_set_domain(rt_uint32_t i) +{ + __asm + { + mcr p15,0, i, c3, c0, 0 + } +} + +void mmu_enable() +{ + register rt_uint32_t value; + + __asm + { + mrc p15, 0, value, c1, c0, 0 + orr value, value, #0x01 + mcr p15, 0, value, c1, c0, 0 + } +} + +void mmu_disable() +{ + register rt_uint32_t value; + + __asm + { + mrc p15, 0, value, c1, c0, 0 + bic value, value, #0x01 + mcr p15, 0, value, c1, c0, 0 + } +} + +void mmu_enable_icache() +{ + register rt_uint32_t value; + + __asm + { + mrc p15, 0, value, c1, c0, 0 + orr value, value, #0x1000 + mcr p15, 0, value, c1, c0, 0 + } +} + +void mmu_enable_dcache() +{ + register rt_uint32_t value; + + __asm + { + mrc p15, 0, value, c1, c0, 0 + orr value, value, #0x04 + mcr p15, 0, value, c1, c0, 0 + } +} + +void mmu_disable_icache() +{ + register rt_uint32_t value; + + __asm + { + mrc p15, 0, value, c1, c0, 0 + bic value, value, #0x1000 + mcr p15, 0, value, c1, c0, 0 + } +} + +void mmu_disable_dcache() +{ + register rt_uint32_t value; + + __asm + { + mrc p15, 0, value, c1, c0, 0 + bic value, value, #0x04 + mcr p15, 0, value, c1, c0, 0 + } +} + +void mmu_enable_alignfault() +{ + register rt_uint32_t value; + + __asm + { + mrc p15, 0, value, c1, c0, 0 + orr value, value, #0x02 + mcr p15, 0, value, c1, c0, 0 + } +} + +void mmu_disable_alignfault() +{ + register rt_uint32_t value; + + __asm + { + mrc p15, 0, value, c1, c0, 0 + bic value, value, #0x02 + mcr p15, 0, value, c1, c0, 0 + } +} + +void mmu_clean_invalidated_cache_index(int index) +{ + __asm + { + mcr p15, 0, index, c7, c14, 2 + } +} + +void mmu_clean_invalidated_dcache(rt_uint32_t buffer, rt_uint32_t size) +{ + unsigned int ptr; + + ptr = buffer & ~0x1f; + + while(ptr < buffer + size) + { + __asm + { + MCR p15, 0, ptr, c7, c14, 1 + } + ptr += 32; + } +} + +void mmu_clean_dcache(rt_uint32_t buffer, rt_uint32_t size) +{ + unsigned int ptr; + + ptr = buffer & ~0x1f; + + while (ptr < buffer + size) + { + __asm + { + MCR p15, 0, ptr, c7, c10, 1 + } + ptr += 32; + } +} + +void mmu_invalidate_dcache(rt_uint32_t buffer, rt_uint32_t size) +{ + unsigned int ptr; + + ptr = buffer & ~0x1f; + + while (ptr < buffer + size) + { + __asm + { + MCR p15, 0, ptr, c7, c6, 1 + } + ptr += 32; + } +} + +void mmu_invalidate_tlb() +{ + register rt_uint32_t value; + + value = 0; + __asm + { + mcr p15, 0, value, c8, c7, 0 + } +} + +void mmu_invalidate_icache() +{ + register rt_uint32_t value; + + value = 0; + + __asm + { + mcr p15, 0, value, c7, c5, 0 + } +} + +#elif defined(__GNUC__) +void mmu_setttbase(register rt_uint32_t i) +{ + register rt_uint32_t value; + + /* Invalidates all TLBs.Domain access is selected as + * client by configuring domain access register, + * in that case access controlled by permission value + * set by page table entry + */ + value = 0; + asm ("mcr p15, 0, %0, c8, c7, 0"::"r"(value)); + + value = 0x55555555; + asm ("mcr p15, 0, %0, c3, c0, 0"::"r"(value)); + asm ("mcr p15, 0, %0, c2, c0, 0"::"r"(i)); +} + +void mmu_set_domain(register rt_uint32_t i) +{ + asm ("mcr p15,0, %0, c3, c0, 0": :"r" (i)); +} + +void mmu_enable() +{ + register rt_uint32_t i; + + /* read control register */ + asm ("mrc p15, 0, %0, c1, c0, 0":"=r" (i)); + + i |= 0x1; + + /* write back to control register */ + asm ("mcr p15, 0, %0, c1, c0, 0": :"r" (i)); +} + +void mmu_disable() +{ + register rt_uint32_t i; + + /* read control register */ + asm ("mrc p15, 0, %0, c1, c0, 0":"=r" (i)); + + i &= ~0x1; + + /* write back to control register */ + asm ("mcr p15, 0, %0, c1, c0, 0": :"r" (i)); +} + +void mmu_enable_icache() +{ + register rt_uint32_t i; + + /* read control register */ + asm ("mrc p15, 0, %0, c1, c0, 0":"=r" (i)); + + i |= (1 << 12); + + /* write back to control register */ + asm ("mcr p15, 0, %0, c1, c0, 0": :"r" (i)); +} + +void mmu_enable_dcache() +{ + register rt_uint32_t i; + + /* read control register */ + asm ("mrc p15, 0, %0, c1, c0, 0":"=r" (i)); + + i |= (1 << 2); + + /* write back to control register */ + asm ("mcr p15, 0, %0, c1, c0, 0": :"r" (i)); +} + +void mmu_disable_icache() +{ + register rt_uint32_t i; + + /* read control register */ + asm ("mrc p15, 0, %0, c1, c0, 0":"=r" (i)); + + i &= ~(1 << 12); + + /* write back to control register */ + asm ("mcr p15, 0, %0, c1, c0, 0": :"r" (i)); +} + +void mmu_disable_dcache() +{ + register rt_uint32_t i; + + /* read control register */ + asm ("mrc p15, 0, %0, c1, c0, 0":"=r" (i)); + + i &= ~(1 << 2); + + /* write back to control register */ + asm ("mcr p15, 0, %0, c1, c0, 0": :"r" (i)); +} + +void mmu_enable_alignfault() +{ + register rt_uint32_t i; + + /* read control register */ + asm ("mrc p15, 0, %0, c1, c0, 0":"=r" (i)); + + i |= (1 << 1); + + /* write back to control register */ + asm ("mcr p15, 0, %0, c1, c0, 0": :"r" (i)); +} + +void mmu_disable_alignfault() +{ + register rt_uint32_t i; + + /* read control register */ + asm ("mrc p15, 0, %0, c1, c0, 0":"=r" (i)); + + i &= ~(1 << 1); + + /* write back to control register */ + asm ("mcr p15, 0, %0, c1, c0, 0": :"r" (i)); +} + +void mmu_clean_invalidated_cache_index(int index) +{ + asm ("mcr p15, 0, %0, c7, c14, 2": :"r" (index)); +} + +void mmu_clean_dcache(rt_uint32_t buffer, rt_uint32_t size) +{ + unsigned int ptr; + + ptr = buffer & ~0x1f; + + while (ptr < buffer + size) + { + asm ("mcr p15, 0, %0, c7, c10, 1": :"r" (ptr)); + ptr += 32; + } +} + +void mmu_invalidate_dcache(rt_uint32_t buffer, rt_uint32_t size) +{ + unsigned int ptr; + + ptr = buffer & ~0x1f; + + while (ptr < buffer + size) + { + asm ("mcr p15, 0, %0, c7, c6, 1": :"r" (ptr)); + ptr += 32; + } +} + +void mmu_invalidate_tlb() +{ + asm ("mcr p15, 0, %0, c8, c7, 0": :"r" (0)); +} + +void mmu_invalidate_icache() +{ + asm ("mcr p15, 0, %0, c7, c5, 0": :"r" (0)); +} +#endif + +/* level1 page table */ +static volatile unsigned int _page_table[4*1024] __attribute__((aligned(16*1024))); +void mmu_setmtt(rt_uint32_t vaddrStart, rt_uint32_t vaddrEnd, rt_uint32_t paddrStart, rt_uint32_t attr) +{ + volatile rt_uint32_t *pTT; + volatile int i,nSec; + pTT=(rt_uint32_t *)_page_table+(vaddrStart>>20); + nSec=(vaddrEnd>>20)-(vaddrStart>>20); + for(i=0;i<=nSec;i++) + { + *pTT = attr |(((paddrStart>>20)+i)<<20); + pTT++; + } +} + +void rt_hw_mmu_init(void) +{ + /* disable I/D cache */ + mmu_disable_dcache(); + mmu_disable_icache(); + mmu_disable(); + mmu_invalidate_tlb(); + + /* set page table */ + mmu_setmtt(0x00000000, 0xFFFFFFFF, 0x00000000, RW_NCNB); /* None cached for 4G memory */ + mmu_setmtt(0xC0000000, 0xC8000000-1, 0xC0000000, RW_CB); /* 128M cached DDR memory */ + mmu_setmtt(0xD0000000, 0xD8000000-1, 0xC0000000, RW_NCNB); /* 128M none-cached DDR memory */ + mmu_setmtt(0x80000000, 0x80020000-1, 0x80000000, RW_CB); /* 128k OnChip memory */ + + /* set MMU table address */ + mmu_setttbase((rt_uint32_t)_page_table); + + /* enables MMU */ + mmu_enable(); + + /* enable Instruction Cache */ + mmu_enable_icache(); + + /* enable Data Cache */ + mmu_enable_dcache(); +} + diff --git a/libcpu/arm/am335x/stack.c b/libcpu/arm/am335x/stack.c new file mode 100644 index 0000000000..e46f34f7cd --- /dev/null +++ b/libcpu/arm/am335x/stack.c @@ -0,0 +1,65 @@ +/* + * File : stack.c + * This file is part of RT-Thread RTOS + * COPYRIGHT (C) 2011, RT-Thread Development Team + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rt-thread.org/license/LICENSE + * + * Change Logs: + * Date Author Notes + * 2011-09-23 Bernard the first version + * 2011-10-05 Bernard add thumb mode + */ +#include <rtthread.h> +#include "am33xx.h" + +/** + * @addtogroup AM33xx + */ +/*@{*/ + +/** + * 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_uint32_t *stk; + + stk = (rt_uint32_t*)stack_addr; + *(stk) = (rt_uint32_t)tentry; /* entry point */ + *(--stk) = (rt_uint32_t)texit; /* lr */ + *(--stk) = 0; /* r12 */ + *(--stk) = 0; /* r11 */ + *(--stk) = 0; /* r10 */ + *(--stk) = 0; /* r9 */ + *(--stk) = 0; /* r8 */ + *(--stk) = 0; /* r7 */ + *(--stk) = 0; /* r6 */ + *(--stk) = 0; /* r5 */ + *(--stk) = 0; /* r4 */ + *(--stk) = 0; /* r3 */ + *(--stk) = 0; /* r2 */ + *(--stk) = 0; /* r1 */ + *(--stk) = (rt_uint32_t)parameter; /* r0 : argument */ + + /* cpsr */ + if ((rt_uint32_t)tentry & 0x01) + *(--stk) = SVCMODE | 0x20; /* thumb mode */ + else + *(--stk) = SVCMODE; /* arm mode */ + + /* return task's current stack address */ + return (rt_uint8_t *)stk; +} + +/*@}*/ diff --git a/libcpu/arm/am335x/start_gcc.S b/libcpu/arm/am335x/start_gcc.S new file mode 100644 index 0000000000..6d9ec8be25 --- /dev/null +++ b/libcpu/arm/am335x/start_gcc.S @@ -0,0 +1,245 @@ +/* + * File : start_gcc.S + * This file is part of RT-Thread RTOS + * COPYRIGHT (C) 2013, RT-Thread Development Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Change Logs: + * Date Author Notes + * 2013-07-05 Bernard the first version + */ + +.equ Mode_USR, 0x10 +.equ Mode_FIQ, 0x11 +.equ Mode_IRQ, 0x12 +.equ Mode_SVC, 0x13 +.equ Mode_ABT, 0x17 +.equ Mode_UND, 0x1B +.equ Mode_SYS, 0x1F + +.equ I_Bit, 0x80 @ when I bit is set, IRQ is disabled +.equ F_Bit, 0x40 @ when F bit is set, FIQ is disabled + +.equ UND_Stack_Size, 0x00000000 +.equ SVC_Stack_Size, 0x00000100 +.equ ABT_Stack_Size, 0x00000000 +.equ FIQ_Stack_Size, 0x00000000 +.equ IRQ_Stack_Size, 0x00000100 +.equ USR_Stack_Size, 0x00000100 + +#define ISR_Stack_Size (UND_Stack_Size + SVC_Stack_Size + ABT_Stack_Size + \ + FIQ_Stack_Size + IRQ_Stack_Size) + +/* stack */ +.globl stack_start +.globl stack_top + +stack_start: +.rept ISR_Stack_Size +.long 0 +.endr +stack_top: + +/* reset entry */ +.globl _reset +_reset: + /* set the cpu to SVC32 mode and disable interrupt */ + mrs r0, cpsr + bic r0, r0, #0x1f + orr r0, r0, #0x13 + msr cpsr_c, r0 + + /* setup stack */ + bl stack_setup + + /* clear .bss */ + mov r0,#0 /* get a zero */ + ldr r1,=__bss_start /* bss start */ + ldr r2,=__bss_end /* bss end */ + +bss_loop: + cmp r1,r2 /* check if data to clear */ + strlo r0,[r1],#4 /* clear 4 bytes */ + blo bss_loop /* loop until done */ + + /* call C++ constructors of global objects */ + ldr r0, =__ctors_start__ + ldr r1, =__ctors_end__ + +ctor_loop: + cmp r0, r1 + beq ctor_end + ldr r2, [r0], #4 + stmfd sp!, {r0-r1} + mov lr, pc + bx r2 + ldmfd sp!, {r0-r1} + b ctor_loop +ctor_end: + + /* start RT-Thread Kernel */ + ldr pc, _rtthread_startup +_rtthread_startup: + .word rtthread_startup + +stack_setup: + ldr r0, =stack_top + + @ Enter Undefined Instruction Mode and set its Stack Pointer + msr cpsr_c, #Mode_UND|I_Bit|F_Bit + mov sp, r0 + sub r0, r0, #UND_Stack_Size + + @ Enter Abort Mode and set its Stack Pointer + msr cpsr_c, #Mode_ABT|I_Bit|F_Bit + mov sp, r0 + sub r0, r0, #ABT_Stack_Size + + @ Enter FIQ Mode and set its Stack Pointer + msr cpsr_c, #Mode_FIQ|I_Bit|F_Bit + mov sp, r0 + sub r0, r0, #FIQ_Stack_Size + + @ Enter IRQ Mode and set its Stack Pointer + msr cpsr_c, #Mode_IRQ|I_Bit|F_Bit + mov sp, r0 + sub r0, r0, #IRQ_Stack_Size + + @ Enter Supervisor Mode and set its Stack Pointer + msr cpsr_c, #Mode_SVC|I_Bit|F_Bit + mov sp, r0 + sub r0, r0, #SVC_Stack_Size + + @ Enter User Mode and set its Stack Pointer + mov sp, r0 + sub sl, sp, #USR_Stack_Size + bx lr + +/* exception handlers: undef, swi, padt, dabt, resv, irq, fiq */ + .align 5 +.globl vector_undef +vector_undef: + sub sp, sp, #72 + stmia sp, {r0 - r12} @/* Calling r0-r12 */ + add r8, sp, #60 + stmdb r8, {sp, lr} @/* Calling SP, LR */ + str lr, [r8, #0] @/* Save calling PC */ + mrs r6, spsr + str r6, [r8, #4] @/* Save CPSR */ + str r0, [r8, #8] @/* Save OLD_R0 */ + mov r0, sp + + bl rt_hw_trap_udef + + .align 5 +.globl vector_swi +vector_swi: + bl rt_hw_trap_swi + + .align 5 +.globl vector_pabt +vector_pabt: + bl rt_hw_trap_pabt + + .align 5 +.globl vector_dabt +vector_dabt: + sub sp, sp, #72 + stmia sp, {r0 - r12} @/* Calling r0-r12 */ + add r8, sp, #60 + stmdb r8, {sp, lr} @/* Calling SP, LR */ + str lr, [r8, #0] @/* Save calling PC */ + mrs r6, spsr + str r6, [r8, #4] @/* Save CPSR */ + str r0, [r8, #8] @/* Save OLD_R0 */ + mov r0, sp + + bl rt_hw_trap_dabt + + .align 5 +.globl vector_resv +vector_resv: + b . + + .align 5 +.globl vector_fiq +vector_fiq: + stmfd sp!,{r0-r7,lr} + bl rt_hw_trap_fiq + ldmfd sp!,{r0-r7,lr} + subs pc,lr,#4 + +.globl rt_interrupt_enter +.globl rt_interrupt_leave +.globl rt_thread_switch_interrupt_flag +.globl rt_interrupt_from_thread +.globl rt_interrupt_to_thread + +.globl rt_current_thread +.globl vmm_thread +.globl vmm_virq_check + +.globl vector_irq +vector_irq: + stmfd sp!, {r0-r12,lr} + + bl rt_interrupt_enter + bl rt_hw_trap_irq + bl rt_interrupt_leave + + @ if rt_thread_switch_interrupt_flag set, jump to + @ rt_hw_context_switch_interrupt_do and don't return + ldr r0, =rt_thread_switch_interrupt_flag + ldr r1, [r0] + cmp r1, #1 + beq rt_hw_context_switch_interrupt_do + + ldmfd sp!, {r0-r12,lr} + subs pc, lr, #4 + +rt_hw_context_switch_interrupt_do: + mov r1, #0 @ clear flag + str r1, [r0] + + ldmfd sp!, {r0-r12,lr}@ reload saved registers + stmfd sp, {r0-r2} @ save r0-r2 + + mrs r0, spsr @ get cpsr of interrupt thread + + sub r1, sp, #4*3 + sub r2, lr, #4 @ save old task's pc to r2 + + @ switch to SVC mode with no interrupt + msr cpsr_c, #I_Bit|F_Bit|Mode_SVC + + stmfd sp!, {r2} @ push old task's pc + stmfd sp!, {r3-r12,lr}@ push old task's lr,r12-r4 + ldmfd r1, {r1-r3} @ restore r0-r2 of the interrupt thread + stmfd sp!, {r1-r3} @ push old task's r0-r2 + stmfd sp!, {r0} @ push old task's cpsr + + ldr r4, =rt_interrupt_from_thread + ldr r5, [r4] + str sp, [r5] @ store sp in preempted tasks's TCB + + ldr r6, =rt_interrupt_to_thread + ldr r6, [r6] + ldr sp, [r6] @ get new task's stack pointer + + ldmfd sp!, {r4} @ pop new task's cpsr to spsr + msr spsr_cxsf, r4 + + ldmfd sp!, {r0-r12,lr,pc}^ @ pop new task's r0-r12,lr & pc, copy spsr to cpsr diff --git a/libcpu/arm/am335x/trap.c b/libcpu/arm/am335x/trap.c new file mode 100644 index 0000000000..925ec56434 --- /dev/null +++ b/libcpu/arm/am335x/trap.c @@ -0,0 +1,182 @@ +/* + * File : trap.c + * This file is part of RT-Thread RTOS + * COPYRIGHT (C) 2006, RT-Thread Develop Team + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rt-thread.org/license/LICENSE + * + * Change Logs: + * Date Author Notes + * 2011-09-23 Bernard first version + */ + +#include <rtthread.h> +#include <rthw.h> + +#include "am33xx.h" +#include "interrupt.h" + +/** + * @addtogroup AM33XX + */ +/*@{*/ + +extern struct rt_thread *rt_current_thread; +#ifdef RT_USING_FINSH +extern long list_thread(void); +#endif + +/** + * this function will show registers of CPU + * + * @param regs the registers point + */ + +void rt_hw_show_register (struct rt_hw_register *regs) +{ + rt_kprintf("Execption:\n"); + rt_kprintf("r00:0x%08x r01:0x%08x r02:0x%08x r03:0x%08x\n", regs->r0, regs->r1, regs->r2, regs->r3); + rt_kprintf("r04:0x%08x r05:0x%08x r06:0x%08x r07:0x%08x\n", regs->r4, regs->r5, regs->r6, regs->r7); + rt_kprintf("r08:0x%08x r09:0x%08x r10:0x%08x\n", regs->r8, regs->r9, regs->r10); + rt_kprintf("fp :0x%08x ip :0x%08x\n", regs->fp, regs->ip); + rt_kprintf("sp :0x%08x lr :0x%08x pc :0x%08x\n", regs->sp, regs->lr, regs->pc); + rt_kprintf("cpsr:0x%08x\n", regs->cpsr); +} + +/** + * When ARM7TDMI comes across an instruction which it cannot handle, + * it takes the undefined instruction trap. + * + * @param regs system registers + * + * @note never invoke this function in application + */ +void rt_hw_trap_udef(struct rt_hw_register *regs) +{ + rt_hw_show_register(regs); + + rt_kprintf("undefined instruction\n"); + rt_kprintf("thread %.*s stack:\n", RT_NAME_MAX, rt_current_thread->name); + +#ifdef RT_USING_FINSH + list_thread(); +#endif + rt_hw_cpu_shutdown(); +} + +/** + * The software interrupt instruction (SWI) is used for entering + * Supervisor mode, usually to request a particular supervisor + * function. + * + * @param regs system registers + * + * @note never invoke this function in application + */ +void rt_hw_trap_swi(struct rt_hw_register *regs) +{ + rt_hw_show_register(regs); + + rt_kprintf("software interrupt\n"); + rt_hw_cpu_shutdown(); +} + +/** + * An abort indicates that the current memory access cannot be completed, + * which occurs during an instruction prefetch. + * + * @param regs system registers + * + * @note never invoke this function in application + */ +void rt_hw_trap_pabt(struct rt_hw_register *regs) +{ + rt_hw_show_register(regs); + + rt_kprintf("prefetch abort\n"); + rt_kprintf("thread %.*s stack:\n", RT_NAME_MAX, rt_current_thread->name); + +#ifdef RT_USING_FINSH + list_thread(); +#endif + rt_hw_cpu_shutdown(); +} + +/** + * An abort indicates that the current memory access cannot be completed, + * which occurs during a data access. + * + * @param regs system registers + * + * @note never invoke this function in application + */ +void rt_hw_trap_dabt(struct rt_hw_register *regs) +{ + rt_hw_show_register(regs); + + rt_kprintf("data abort\n"); + rt_kprintf("thread %.*s stack:\n", RT_NAME_MAX, rt_current_thread->name); + +#ifdef RT_USING_FINSH + list_thread(); +#endif + rt_hw_cpu_shutdown(); +} + +void rt_hw_trap_irq() +{ + void *param; + unsigned long ir; + rt_isr_handler_t isr_func; + extern struct rt_irq_desc isr_table[]; + + ir = rt_hw_interrupt_get_active(INT_IRQ); + if (ir == 127) + { + /* new IRQ generation */ + rt_hw_interrupt_ack(INT_IRQ); + ir = rt_hw_interrupt_get_active(INT_IRQ); + if (ir == 127) + { + /* still spurious interrupt, get out */ + /*rt_kprintf("still spurious interrupt\n");*/ + return; + } + /*rt_kprintf("new IRQ: %d\n", ir);*/ + } + + /* get interrupt service routine */ + isr_func = isr_table[ir].handler; + param = isr_table[ir].param; + + /* turn to interrupt service routine */ + if (isr_func != RT_NULL) + isr_func(ir, param); + + /* new IRQ generation */ + rt_hw_interrupt_ack(INT_IRQ); +} + +void rt_hw_trap_fiq() +{ + void *param; + unsigned long ir; + rt_isr_handler_t isr_func; + extern struct rt_irq_desc isr_table[]; + + ir = rt_hw_interrupt_get_active(INT_FIQ); + + /* get interrupt service routine */ + isr_func = isr_table[ir].handler; + param = isr_table[ir].param; + + /* turn to interrupt service routine */ + isr_func(ir, param); + + /* new FIQ generation */ + rt_hw_interrupt_ack(INT_FIQ); +} + +/*@}*/ diff --git a/libcpu/arm/am335x/vector_gcc.S b/libcpu/arm/am335x/vector_gcc.S new file mode 100644 index 0000000000..4a44a7395c --- /dev/null +++ b/libcpu/arm/am335x/vector_gcc.S @@ -0,0 +1,65 @@ +/* + * File : vector_gcc.S + * This file is part of RT-Thread RTOS + * COPYRIGHT (C) 2013, RT-Thread Development Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Change Logs: + * Date Author Notes + * 2013-07-05 Bernard the first version + */ + +.section .vectors, "ax" +.code 32 + +.globl system_vectors +system_vectors: + ldr pc, _vector_reset + ldr pc, _vector_undef + ldr pc, _vector_swi + ldr pc, _vector_pabt + ldr pc, _vector_dabt + ldr pc, _vector_resv + ldr pc, _vector_irq + ldr pc, _vector_fiq + +.globl _reset +.globl vector_undef +.globl vector_swi +.globl vector_pabt +.globl vector_dabt +.globl vector_resv +.globl vector_irq +.globl vector_fiq + +_vector_reset: + .word _reset +_vector_undef: + .word vector_undef +_vector_swi: + .word vector_swi +_vector_pabt: + .word vector_pabt +_vector_dabt: + .word vector_dabt +_vector_resv: + .word vector_resv +_vector_irq: + .word vector_irq +_vector_fiq: + .word vector_fiq + +.balignl 16,0xdeadbeef |
