FreeCalypso > hg > ffs-editor
diff src/cs/system/main/int.s @ 0:92470e5d0b9e
src: partial import from FC Selenite
author | Mychaela Falconia <falcon@freecalypso.org> |
---|---|
date | Fri, 15 May 2020 01:28:16 +0000 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/cs/system/main/int.s Fri May 15 01:28:16 2020 +0000 @@ -0,0 +1,2255 @@ +;****************************************************************************** +; TEXAS INSTRUMENTS INCORPORATED PROPRIETARY INFORMATION +; +; Property of Texas Instruments -- For Unrestricted Internal Use Only +; Unauthorized reproduction and/or distribution is strictly prohibited. This +; product is protected under copyright law and trade secret law as an +; unpublished work. Created 1987, (C) Copyright 1997 Texas Instruments. All +; rights reserved. +; +; +; Filename : int.s +; +; Description : Nucleus initialization +; +; Project : Drivers +; +; Author : proussel@ti.com Patrick Roussel. +; +; Version number : 1.3 +; +; Date and time : 07/23/98 15:36:07 +; +; Previous delta : 07/23/98 15:36:06 +; +; SCCS file : /db/gsm_asp/db_ht96/dsp_0/gsw/rel_0/mcu_l1/release1.5/mod/emu/EMU_MCMP/eva3_drivers/source/SCCS/s.int.s +; +; Sccs Id (SID) : '@(#) int.s 1.3 07/23/98 15:36:07 ' +;/*************************************************************************/ +;/* */ +;/* Copyright (c) 1993 - 1996 Accelerated Technology, Inc. */ +;/* */ +;/* PROPRIETARY RIGHTS of Accelerated Technology are involved in the */ +;/* subject matter of this material. All manufacturing, reproduction, */ +;/* use, and sales rights pertaining to this subject matter are governed */ +;/* by the license agreement. The recipient of this software implicitly */ +;/* accepts the terms of the license. */ +;/* */ +;/*************************************************************************/ +; +;/*************************************************************************/ +;/* */ +;/* FILE NAME VERSION */ +;/* */ +;/* int.s PLUS/THUMB/T 1.3 */ +;/* */ +;/* COMPONENT */ +;/* */ +;/* IN - Initialization */ +;/* */ +;/* DESCRIPTION */ +;/* */ +;/* This file contains the target processor dependent initialization */ +;/* routines and data. */ +;/* */ +;/* AUTHOR */ +;/* */ +;/* Barry Sellew, Accelerated Technology, Inc. */ +;/* */ +;/* DATA STRUCTURES */ +;/* */ +;/* INT_Vectors Interrupt vector table */ +;/* */ +;/* FUNCTIONS */ +;/* */ +;/* INT_Initialize Target initialization */ +;/* INT_Vectors_Loaded Returns a NU_TRUE if all the */ +;/* default vectors are loaded */ +;/* INT_Setup_Vector Sets up an actual vector */ +;/* */ +;/* DEPENDENCIES */ +;/* */ +;/* nucleus.h System constants */ +;/* */ +;/* HISTORY */ +;/* */ +;/* NAME DATE REMARKS */ +;/* */ +;/* B. Sellew 01-19-1996 Created initial version 1.0 */ +;/* B. Sellew 01-22-1996 Verified version 1.0 */ +;/* B. Sellew 03-14-1996 Modified to use the ROM */ +;/* initialization method, */ +;/* resulting in version 1.1 */ +;/* B. Sellew 03-14-1996 Verified version 1.1 */ +;/* B. Sellew 02-06-1997 Created version 1.3 */ +;/* B. Sellew 02-06-1997 Verified version 1.3 */ +;/* M. Manning 06-02-1997 Added support for FIQ */ +;/* interrupts. Bumped to 1.4 */ +;/* M. Manning 06-03-1997 Verified version 1.4 */ +;/* */ +;/*************************************************************************/ +;#define NU_SOURCE_FILE +; +;#include "nucleus.h" /* System constants */ +; +; +;/* Define constants used in low-level initialization. */ +; +; + + + .if LONG_JUMP >= 3 + .global IND_CALL + .global _f_load_int_mem + .global _ResetVector + +; Initialization for variable S_D_Mem + .sect ".cinit" + .align 4 + +; S_D_Mem is a UWORD32, See mem_load.c +; + .field 4,32 + .field _S_D_Mem+0,32 + .field 0,32 ; _S_D_Mem @ 0 + + .sect ".text" + .global _S_D_Mem +_S_D_Mem: .usect "S_D_Mem",4,4 + .sym _S_D_Mem,_S_D_Mem,14,2,32 ; For debug only + + +; Initialization for variable E_D_Mem + + .sect ".cinit" + .align 4 + + +; E_D_Mem is a UWORD32, See mem_load.c +; + .field 4,32 + .field _E_D_Mem+0,32 + .field 0,32 ; _E_D_Mem @ 0 + + .sect ".text" + .global _E_D_Mem +_E_D_Mem: .usect "E_D_Mem",4,4 + .sym _E_D_Mem,_E_D_Mem,14,2,32 ; For debug only + + .endif ; (LONG_JUMP >= 3) + + .if CHIPSET == 12 + .global _f_load_int_mem + .global _ResetVector + .global _ResetVectorTestMode ; CALYPSO PLUS TEST MODE - TO BE ERASED + .endif + +LOCKOUT .equ 00C0h ; Interrupt lockout value +LOCK_MSK .equ 00C0h ; Interrupt lockout mask value +MODE_MASK .equ 001Fh ; Processor Mode Mask +SUP_MODE .equ 0013h ; Supervisor Mode (SVC) +IRQ_MODE .equ 0012h ; Interrupt Mode (IRQ) +FIQ_MODE .equ 0011h ; Fast Interrupt Mode (FIQ) +ABORT_MODE .equ 0017h ; Abort Interrupt Mode +UNDEF_MODE .equ 001Bh ; Undefined Interrupt Mode (should not happen) + +IRQ_STACK_SIZE .equ 128 ; Number of bytes in IRQ stack (must be align(8)) + ; Note that the IRQ interrupt, + ; by default, is managed by + ; Nucleus PLUS. Only several + ; words are actually used. The + ; system stack is what will + ; actually be used for Nuclues + ; PLUS managed IRQ interrupts. +FIQ_STACK_SIZE .equ 512 ; Number of bytes in FIQ stack. (must be align(8)) + ; This value is application + ; specific. By default, Nucleus + ; does not manage FIQ interrupts + ; and furthermore, leaves them + ; enabled virtually all the time. +SYSTEM_SIZE .equ 1024 ; Define the system stack size (must be align(8)) +TIMER_SIZE .equ 1024 ; Define timer HISR stack size (must be align(8)) +TIMER_PRIORITY .equ 2 ; Timer HISR priority (values from + + .if BOARD = 34 +; Name value offset type W/E W/S D/Cycles +CS0_CONFIG .short 0x044F ; 0 Flash 32 N F 2 +CS1_CONFIG .short 0x02CF ; 2 RAM 32 Y F 1 +CS2_CONFIG .short 0x02CF ; 4 +CS3_CONFIG .short 0x02CF ; 6 +CS7_CONFIG .short 0x02C0 ; 8 Int-RAM 32 Y 0 1 +CS5_CONFIG .short 0x02CF ; A +CS6_CONFIG .short 0x02C0 ; C Int-RAM 32 Y 0 1 +RHEA_CONFIG .short 0x002A ; E ARM -> RHEA/API adaptation +NUM_CS_REGS .equ 8 ; number of Chip Select Config regs to program + .endif + ; 0 to 2, where 0 is highest) + +; +;/* End of low-level initialization constants. */ +; +; +;/* Define the initialization flag that indicates whether or not all of the +; default vectors have been loaded during initialization. */ +; +;INT INT_Loaded_Flag; + + .def _INT_Loaded_Flag + .bss _INT_Loaded_Flag, 4, 4 +; +;/* Define the vector table */ +; + + .if CHIPSET = 12 + .sect ".start" + + .ref _INT_Bootloader_Start + +_ResetVector: + B _INT_Bootloader_Start + + .sect ".indint" + + .def _IndirectVectorTable +_IndirectVectorTable: + LDR PC, [PC, #0x14] + LDR PC, [PC, #0x14] + LDR PC, [PC, #0x14] + LDR PC, [PC, #0x14] + LDR PC, [PC, #0x14] + LDR PC, [PC, #0x14] + LDR PC, [PC, #0x14] + + .word INT_Undef_Inst + .word INT_Swi + .word INT_Abort_Prefetch + .word INT_Abort_Data + .word INT_Reserved + .word INT_IRQ + .word INT_FIQ + +; CALYPSO PLUS TEST MODE - TO BE ERASED + .sect ".intvecs" + +_ResetVectorTestMode: + B _INT_Bootloader_Start + B INT_Undef_Inst + B INT_Swi + B INT_Abort_Prefetch + B INT_Abort_Data + B INT_Reserved + B INT_IRQ + B INT_FIQ + + .else ; CHIPSET = 12 + + .sect ".intvecs" + + .if BOARD = 34 + B _INT_Initialize + .elseif BOARD = 35 + B _INT_Initialize + .else + .ref _INT_Bootloader_Start + + B _INT_Bootloader_Start + .endif + B INT_Undef_Inst + B INT_Swi + B INT_Abort_Prefetch + B INT_Abort_Data + B INT_Reserved + B Vect_IRQ + .if WCP_PROF = 1 + .global _PR_StoreMonteCarloSample + +; Timing profiler using FIQ - Handle FIQ directly here + + STMFD sp!,{R0-R4, LR} ; Save R0-R4 and LR on FIQ stack + + MOV R0, LR ; Retrieve link register in R0 + BL _PR_StoreMonteCarloSample ; Store into ring buffer + BL _IQ_FIQ_isr ; Ack FIQ + + LDMFD sp!,{R0-R4, LR} ; Restore R0-R4 and LR from FIQ stack + SUBS PC, LR, #4 ; return from FIQ + .else + B Vect_FIQ + .endif + .endif ; CHIPSET = 12 + +; +; .text +; +; .ref cinit + + .sect ".inttext" + .global cinit ; Linker symbol for C variable init. + + +; Address definitions in the section where they are used. + +; +;/* Define the global system stack variable. This is setup by the +; initialization routine. */ +; +;extern VOID *TCD_System_Stack; +; + .ref _TCD_System_Stack + .ref _TCT_System_Limit +; +; +;/* Define the global data structures that need to be initialized by this +; routine. These structures are used to define the system timer management +; HISR. */ +; +;extern VOID *TMD_HISR_Stack_Ptr; +;extern UNSIGNED TMD_HISR_Stack_Size; +;extern INT TMD_HISR_Priority; +; + .ref _TMD_HISR_Stack_Ptr + .ref _TMD_HISR_Stack_Size + .ref _TMD_HISR_Priority +; +; +;/* Define extern function references. */ +; +;VOID INC_Initialize(VOID *first_available_memory); +;VOID TCT_Interrupt_Context_Save(VOID); +;VOID TCT_Interrupt_Context_Restore(VOID); +;VOID TCC_Dispatch_LISR(INT vector_number); +;VOID TMT_Timer_Interrupt(void); +; + .ref _INC_Initialize + .ref _TCT_Interrupt_Context_Save + .ref _TCT_Interrupt_Context_Restore + .ref _TCC_Dispatch_LISR + .ref _TMT_Timer_Interrupt + +;/* Application ISR */ + .ref _IQ_IRQ_isr + .ref _IQ_FIQ_isr +; +; /* Reference pointers defined by the linker */ +; + .ref .bss + .ref end + + .if C155_TARGET = 1 + .def INT_C155_Boot_Entry +INT_C155_Boot_Entry + B _INT_Initialize + .endif + +; +;/* Define indirect branching labels for the vector table */ +; + + .def INT_Undef_Inst +INT_Undef_Inst + B arm_undefined ; Undefined +; + .def INT_Swi +INT_Swi + B arm_swi ; Software Generated +; + .def INT_Abort_Prefetch +INT_Abort_Prefetch + B arm_abort_prefetch ; Abort Prefetch +; + .def INT_Abort_Data +INT_Abort_Data + B arm_abort_data ; Abort Data +; + .def INT_Reserved +INT_Reserved + B arm_reserved ; Reserved +; + .def Vect_IRQ +Vect_IRQ + .if TI_NUC_MONITOR = 1 + B _INT_IRQ + .else + B INT_IRQ + .endif +; + .def Vect_FIQ +Vect_FIQ + .if TI_PROFILER = 1 + B _INT_FIQ + .else + B INT_FIQ + .endif +; + +; +;/*************************************************************************/ +;/* */ +;/* FUNCTION */ +;/* */ +;/* INT_Initialize */ +;/* */ +;/* DESCRIPTION */ +;/* */ +;/* This function sets up the global system stack variable and */ +;/* transfers control to the target independent initialization */ +;/* function INC_Initialize. Responsibilities of this function */ +;/* include the following: */ +;/* */ +;/* - Setup necessary processor/system control registers */ +;/* - Initialize the vector table */ +;/* - Setup the system stack pointers */ +;/* - Setup the timer interrupt */ +;/* - Calculate the timer HISR stack and priority */ +;/* - Calculate the first available memory address */ +;/* - Transfer control to INC_Initialize to initialize all of */ +;/* the system components. */ +;/* */ +;/* AUTHOR */ +;/* */ +;/* Barry Sellew, Accelerated Technology, Inc. */ +;/* */ +;/* CALLED BY */ +;/* */ +;/* none */ +;/* */ +;/* CALLS */ +;/* */ +;/* INC_Initialize Common initialization */ +;/* */ +;/* INPUTS */ +;/* */ +;/* None */ +;/* */ +;/* OUTPUTS */ +;/* */ +;/* None */ +;/* */ +;/* HISTORY */ +;/* */ +;/* NAME DATE REMARKS */ +;/* */ +;/* B. Sellew 01-19-1996 Created initial version 1.0 */ +;/* B. Sellew 01-22-1996 Verified version 1.0 */ +;/* */ +;/*************************************************************************/ +;VOID INT_Initialize(void) +;{ + .def _c_int00 +_c_int00 + + .include "init.asm" + +addrCS0 .word 0xfffffb00 ; CS0 address space + + .if BOARD = 34 +CSConfigTable .long CS0_CONFIG +CS7_SIZE .equ 0x2000 ; 8 kB +CS7_ADDR .equ 0x03800000 ; initial address before toggling nIBOOT +SRAM_ADDR .equ 0x03000000 ; Internal SRAM start address +SRAM_SIZE .equ 0x00040000 ; 256kB +EXTRA_CONF .short 0x013E ; Boot configuration +DEF_EXTRA_CONF .short 0x063E ; Default configuration +addrCS7 .word 0xFFFFFB08 ; CS7 configuration +addrExtraConf .word 0xFFFFFB10 ; Extra configuration +armio_in .word 0xFFFE4800 ; ARMIO_IN register address +armio_out .word 0xFFFE4802 ; ARMIO_OUT register address + .endif + + .if BOARD = 40 | 41 +EX_MPU_CONF_REG .word 0xFFFEF006 ; Extended MPU configuration register address +EX_FLASH_VALUE .short 0x0008 ; set bit to enable A22 + .endif + + .if CHIPSET = 4 +CNTL_ARM_CLK_REG .word 0xFFFFFD00 ; CNTL_ARM_CLK register address +DPLL_CNTRL_REG .word 0xFFFF9800 ; DPLL control register address +RHEA_CNTL_REG .word 0xFFFFF900 ; RHEA control register address + + +CNTL_ARM_CLK_RST .short 0x1081 ; Initialization of CNTL_ARM_CLK register + ; Use DPLL, Divide by 1 +DPLL_CONTROL_RST .short 0x2002 ; Configure DPLL in default state +RHEA_CONTROL_RST .short 0xFF22 ; Set access factor in order to access the DPLL register + ; independently of the ARM clock + .elseif CHIPSET = 6 +CNTL_ARM_CLK_REG .word 0xFFFFFD00 ; CNTL_ARM_CLK register address +CNTLCLK_26MHZ_SELECTOR .short 0x0040 ; VTCXO_26 selector + + .elseif CHIPSET = 7 +CNTL_ARM_CLK_REG .word 0xFFFFFD00 ; CNTL_ARM_CLK register address +DPLL_CNTRL_REG .word 0xFFFF9800 ; DPLL control register address +EXTRA_CONTROL_REG .word 0xFFFFFB10 ; Extra Control register CONF address +MPU_CTL_REG .word 0xFFFFFF08 ; MPU_CTL register address + +CNTL_ARM_CLK_RST .short 0x1081 ; Initialization of CNTL_ARM_CLK register + ; Use DPLL, Divide by 1 +DPLL_CONTROL_RST .short 0x2002 ; Configure DPLL in default state +DISABLE_DU_MASK .short 0x0800 ; Mask to Disable the DU module +ENABLE_DU_MASK .short 0xF7FF ; Mask to Enable the DU module +MPU_CTL_RST .short 0x0000 ; Reset value of MPU_CTL register - All protections disabled + + .elseif CHIPSET = 8 +CNTL_ARM_CLK_REG .word 0xFFFFFD00 ; CNTL_ARM_CLK register address +DPLL_CNTRL_REG .word 0xFFFF9800 ; DPLL control register address +EXTRA_CONTROL_REG .word 0xFFFFFB10 ; Extra Control register CONF address +MPU_CTL_REG .word 0xFFFFFF08 ; MPU_CTL register address + +CNTL_ARM_CLK_RST .short 0x1081 ; Initialization of CNTL_ARM_CLK register + ; Use DPLL, Divide by 1 +DPLL_CONTROL_RST .short 0x2002 ; Configure DPLL in default state +DISABLE_DU_MASK .short 0x0800 ; Mask to Disable the DU module +ENABLE_DU_MASK .short 0xF7FF ; Mask to Enable the DU module +MPU_CTL_RST .short 0x0000 ; Reset value of MPU_CTL register - All protections disabled + + .elseif CHIPSET = 10 +CNTL_ARM_CLK_REG .word 0xFFFFFD00 ; CNTL_ARM_CLK register address +DPLL_CNTRL_REG .word 0xFFFF9800 ; DPLL control register address +EXTRA_CONTROL_REG .word 0xFFFFFB10 ; Extra Control register CONF address +MPU_CTL_REG .word 0xFFFFFF08 ; MPU_CTL register address + +CNTL_ARM_CLK_RST .short 0x1081 ; Initialization of CNTL_ARM_CLK register + ; Use DPLL, Divide by 1 +DPLL_CONTROL_RST .short 0x2002 ; Configure DPLL in default state +DISABLE_DU_MASK .short 0x0800 ; Mask to Disable the DU module +ENABLE_DU_MASK .short 0xF7FF ; Mask to Enable the DU module +MPU_CTL_RST .short 0x0000 ; Reset value of MPU_CTL register - All protections disabled + + .elseif CHIPSET = 11 +CNTL_ARM_CLK_REG .word 0xFFFFFD00 ; CNTL_ARM_CLK register address +DPLL_CNTRL_REG .word 0xFFFF9800 ; DPLL control register address +EXTRA_CONTROL_REG .word 0xFFFFFB10 ; Extra Control register CONF address +MPU_CTL_REG .word 0xFFFFFF08 ; MPU_CTL register address + +CNTL_ARM_CLK_RST .short 0x1081 ; Initialization of CNTL_ARM_CLK register + ; Use DPLL, Divide by 1 +DPLL_CONTROL_RST .short 0x2002 ; Configure DPLL in default state +DISABLE_DU_MASK .short 0x0800 ; Mask to Disable the DU module +ENABLE_DU_MASK .short 0xF7FF ; Mask to Enable the DU module +MPU_CTL_RST .short 0x0000 ; Reset value of MPU_CTL register - All protections disabled + + .elseif CHIPSET = 12 +DBG_DMA_P2 .word 0xFFFEF02C ; DBG_DMA_P2 register address +CNTL_ARM_CLK_REG .word 0xFFFFFD00 ; CNTL_ARM_CLK register address +DPLL_CNTRL_REG .word 0xFFFF9800 ; DPLL control register address +EXTRA_CONTROL_REG .word 0xFFFFFB10 ; Extra Control register CONF address +MPU_CTL_REG .word 0xFFFFFF08 ; MPU_CTL register address + +CNTL_ARM_CLK_RST .short 0x1081 ; Initialization of CNTL_ARM_CLK register + ; Use DPLL, Divide by 1 +DPLL_CONTROL_RST .short 0x2006 ; Configure DPLL in default state +DISABLE_DU_MASK .short 0x0800 ; Mask to Disable the DU module +MPU_CTL_RST .short 0x0000 ; Reset value of MPU_CTL register - All protections disabled +DBG_DMA_P2_RST .short 0x0002 ; DBG_DMA_P2 register reset value + .endif ; CHIPSET = 4 or 6 or 7 or 8 or 10 or 11 or 12 + + +c_cinit .long cinit + + .def _INT_Initialize +_INT_Initialize + +; +; Configuration of ARM clock and DPLL frequency +; + .if CHIPSET = 4 +; +; Configure RHEA access factor in order to allow the access of DPLL register +; + ldr r1,RHEA_CNTL_REG ; Load address of RHEA control register in R1 + ldrh r2,RHEA_CONTROL_RST ; Load RHEA configuration value in R2 + strh r2,[r1] ; Store DPLL reset value in RHEA control register + +; +; Configure DPLL register with reset value +; + ldr r1,DPLL_CNTRL_REG ; Load address of DPLL register in R1 + ldrh r2,DPLL_CONTROL_RST ; Load DPLL reset value in R2 + strh r2,[r1] ; Store DPLL reset value in DPLL register + +; +; Wait that DPLL goes in BYPASS mode +; +Wait_DPLL_Bypass + ldr r2,[r1] ; Load DPLL register + and r2,r2,#1 ; Perform a mask on bit 0 + cmp r2,#1 ; Compare DPLL lock bit + beq Wait_DPLL_Bypass ; Wait Bypass mode (i.e. bit[0]='0') + +; +; Configure CNTL_ARM_CLK register with reset value: DPLL is used to +; generate ARM clock with division factor of 1. +; + ldr r1,CNTL_ARM_CLK_REG ; Load address of CNTL_ARM_CLK register in R1 + ldrh r2,CNTL_ARM_CLK_RST ; Load CNTL_ARM_CLK reset value in R2 + strh r2,[r1] ; Store CNTL_ARM_CLK reset value in CNTL_ARM_CLK register + + .elseif CHIPSET = 6 + +; +; Set VTCXO_26MHZ bit to '1' in case of the VTCXO clock is 26MHz instead +; of 13MHz. +; + ldr r1, CNTL_ARM_CLK_REG ; Load CLKM base register address in R1 + ldrh r2, [r1,#2] ; Load contents of CNTL_CLK register in R2 + ldr r0, CNTLCLK_26MHZ_SELECTOR ; Load configuration of 26MHz selector + orr r0, r0, r2; + strh r0, [r1,#2]; + +; Wait a while until clock is stable (required for AvengerII) + mov r0,#0x100 +WaitAWhile1: + sub r0, r0, #1 + cmp r0, #0 + bne WaitAWhile1 + + .elseif CHIPSET = 7 +; +; Configure DPLL register with reset value +; + ldr r1,DPLL_CNTRL_REG ; Load address of DPLL register in R1 + ldrh r2,DPLL_CONTROL_RST ; Load DPLL reset value in R2 + strh r2,[r1] ; Store DPLL reset value in DPLL register + +; +; Wait that DPLL goes in BYPASS mode +; +Wait_DPLL_Bypass + ldr r2,[r1] ; Load DPLL register + and r2,r2,#1 ; Perform a mask on bit 0 + cmp r2,#1 ; Compare DPLL lock bit + beq Wait_DPLL_Bypass ; Wait Bypass mode (i.e. bit[0]='0') + +; +; Configure CNTL_ARM_CLK register with reset value: DPLL is used to +; generate ARM clock with division factor of 1. +; + ldr r1,CNTL_ARM_CLK_REG ; Load address of CNTL_ARM_CLK register in R1 + ldrh r2,CNTL_ARM_CLK_RST ; Load CNTL_ARM_CLK reset value in R2 + strh r2,[r1] ; Store CNTL_ARM_CLK reset value in CNTL_ARM_CLK register + +; +; Disable/Enable the DU module by setting/resetting bit 11 to '1'/'0' +; + ldr r1,EXTRA_CONTROL_REG ; Load address of Extra Control register CONF + ;ldrh r2,DISABLE_DU_MASK ; Load mask to write in Extra Control register CONF + ldrh r2,ENABLE_DU_MASK ; Load mask to write in Extra Control register CONF + ldrh r0,[r1] ; Load Extra Control register CONF in r0 + ;orr r0,r0,r2 ; Disable DU module + and r0,r0,r2 ; Enable DU module + strh r0,[r1] ; Store configuration in Extra Control register CONF + +; +; Disable all MPU protections +; + ldr r1,MPU_CTL_REG ; Load address of MPU_CTL register + ldrh r2,MPU_CTL_RST ; Load reset value of MPU_CTL register + strh r2,[r1] ; Store reset value of MPU_CTL register + + .elseif CHIPSET = 8 +; +; Configure DPLL register with reset value +; + ldr r1,DPLL_CNTRL_REG ; Load address of DPLL register in R1 + ldrh r2,DPLL_CONTROL_RST ; Load DPLL reset value in R2 + strh r2,[r1] ; Store DPLL reset value in DPLL register + +; +; Wait that DPLL goes in BYPASS mode +; +Wait_DPLL_Bypass + ldr r2,[r1] ; Load DPLL register + and r2,r2,#1 ; Perform a mask on bit 0 + cmp r2,#1 ; Compare DPLL lock bit + beq Wait_DPLL_Bypass ; Wait Bypass mode (i.e. bit[0]='0') + +; +; Configure CNTL_ARM_CLK register with reset value: DPLL is used to +; generate ARM clock with division factor of 1. +; + ldr r1,CNTL_ARM_CLK_REG ; Load address of CNTL_ARM_CLK register in R1 + ldrh r2,CNTL_ARM_CLK_RST ; Load CNTL_ARM_CLK reset value in R2 + strh r2,[r1] ; Store CNTL_ARM_CLK reset value in CNTL_ARM_CLK register + +; +; Disable/Enable the DU module by setting/resetting bit 11 to '1'/'0' +; + ldr r1,EXTRA_CONTROL_REG ; Load address of Extra Control register CONF + ;ldrh r2,DISABLE_DU_MASK ; Load mask to write in Extra Control register CONF + ldrh r2,ENABLE_DU_MASK ; Load mask to write in Extra Control register CONF + ldrh r0,[r1] ; Load Extra Control register CONF in r0 + ;orr r0,r0,r2 ; Disable DU module + and r0,r0,r2 ; Enable DU module + strh r0,[r1] ; Store configuration in Extra Control register CONF + +; +; Disable all MPU protections +; + ldr r1,MPU_CTL_REG ; Load address of MPU_CTL register + ldrh r2,MPU_CTL_RST ; Load reset value of MPU_CTL register + strh r2,[r1] ; Store reset value of MPU_CTL register + + .elseif CHIPSET = 10 +; +; Configure DPLL register with reset value +; + ldr r1,DPLL_CNTRL_REG ; Load address of DPLL register in R1 + ldrh r2,DPLL_CONTROL_RST ; Load DPLL reset value in R2 + strh r2,[r1] ; Store DPLL reset value in DPLL register + +; +; Wait that DPLL goes in BYPASS mode +; +Wait_DPLL_Bypass + ldr r2,[r1] ; Load DPLL register + and r2,r2,#1 ; Perform a mask on bit 0 + cmp r2,#1 ; Compare DPLL lock bit + beq Wait_DPLL_Bypass ; Wait Bypass mode (i.e. bit[0]='0') + +; +; Configure CNTL_ARM_CLK register with reset value: DPLL is used to +; generate ARM clock with division factor of 1. +; + ldr r1,CNTL_ARM_CLK_REG ; Load address of CNTL_ARM_CLK register in R1 + ldrh r2,CNTL_ARM_CLK_RST ; Load CNTL_ARM_CLK reset value in R2 + strh r2,[r1] ; Store CNTL_ARM_CLK reset value in CNTL_ARM_CLK register + +; +; Disable/Enable the DU module by setting/resetting bit 11 to '1'/'0' +; + ldr r1,EXTRA_CONTROL_REG ; Load address of Extra Control register CONF + ;ldrh r2,DISABLE_DU_MASK ; Load mask to write in Extra Control register CONF + ldrh r2,ENABLE_DU_MASK ; Load mask to write in Extra Control register CONF + ldrh r0,[r1] ; Load Extra Control register CONF in r0 + ;orr r0,r0,r2 ; Disable DU module + and r0,r0,r2 ; Enable DU module + strh r0,[r1] ; Store configuration in Extra Control register CONF + +; +; Disable all MPU protections +; + ldr r1,MPU_CTL_REG ; Load address of MPU_CTL register + ldrh r2,MPU_CTL_RST ; Load reset value of MPU_CTL register + strh r2,[r1] ; Store reset value of MPU_CTL register + + .elseif CHIPSET = 11 +; +; Configure DPLL register with reset value +; + ldr r1,DPLL_CNTRL_REG ; Load address of DPLL register in R1 + ldrh r2,DPLL_CONTROL_RST ; Load DPLL reset value in R2 + strh r2,[r1] ; Store DPLL reset value in DPLL register + +; +; Wait that DPLL goes in BYPASS mode +; +Wait_DPLL_Bypass + ldr r2,[r1] ; Load DPLL register + and r2,r2,#1 ; Perform a mask on bit 0 + cmp r2,#1 ; Compare DPLL lock bit + beq Wait_DPLL_Bypass ; Wait Bypass mode (i.e. bit[0]='0') + +; +; Configure CNTL_ARM_CLK register with reset value: DPLL is used to +; generate ARM clock with division factor of 1. +; + ldr r1,CNTL_ARM_CLK_REG ; Load address of CNTL_ARM_CLK register in R1 + ldrh r2,CNTL_ARM_CLK_RST ; Load CNTL_ARM_CLK reset value in R2 + strh r2,[r1] ; Store CNTL_ARM_CLK reset value in CNTL_ARM_CLK register + +; +; Disable/Enable the DU module by setting/resetting bit 11 to '1'/'0' +; + ldr r1,EXTRA_CONTROL_REG ; Load address of Extra Control register CONF + ;ldrh r2,DISABLE_DU_MASK ; Load mask to write in Extra Control register CONF + ldrh r2,ENABLE_DU_MASK ; Load mask to write in Extra Control register CONF + ldrh r0,[r1] ; Load Extra Control register CONF in r0 + ;orr r0,r0,r2 ; Disable DU module + and r0,r0,r2 ; Enable DU module + strh r0,[r1] ; Store configuration in Extra Control register CONF + +; +; Disable all MPU protections +; + ldr r1,MPU_CTL_REG ; Load address of MPU_CTL register + ldrh r2,MPU_CTL_RST ; Load reset value of MPU_CTL register + strh r2,[r1] ; Store reset value of MPU_CTL register + + .elseif CHIPSET = 12 + + .if BOARD = 6 + ; Configure DBG_DMA_P2 reg => GPO_2 output pin for EVA4 + ldr r1,DBG_DMA_P2 ; Load address of DBG_DMA_P2 register in R1 + ldrh r2,DBG_DMA_P2_RST ; Load DBG_DMA_P2 reset value in R2 + strh r2,[r1] ; Store reset value in register + ; + .endif ; BOARD = 6 + + ; + ; Configure DPLL register with reset value + ; + ldr r1,DPLL_CNTRL_REG ; Load address of DPLL register in R1 + ldrh r2,DPLL_CONTROL_RST ; Load DPLL reset value in R2 + strh r2,[r1] ; Store DPLL reset value in DPLL register + +; +; Wait that DPLL goes in BYPASS mode +; +Wait_DPLL_Bypass + ldr r2,[r1] ; Load DPLL register + and r2,r2,#1 ; Perform a mask on bit 0 + cmp r2,#1 ; Compare DPLL lock bit + beq Wait_DPLL_Bypass ; Wait Bypass mode (i.e. bit[0]='0') + + ; + ; Configure CNTL_ARM_CLK register with reset value: DPLL is used to + ; generate ARM clock with division factor of 1. + ; + ldr r1,CNTL_ARM_CLK_REG ; Load address of CNTL_ARM_CLK register in R1 + ldrh r2,CNTL_ARM_CLK_RST ; Load CNTL_ARM_CLK reset value in R2 + strh r2,[r1] ; Store CNTL_ARM_CLK reset value in CNTL_ARM_CLK register + +; +; Disable the DU module by setting bit 11 to '1' +; +; ldr r1,EXTRA_CONTROL_REG ; Load address of Extra Control register CONF +; ldrh r2,DISABLE_DU_MASK ; Load mask to write in Extra Control register CONF +; ldrh r0,[r1] ; Load Extra Control register CONF in r0 +; orr r0,r0,r2 ; Disable DU module +; strh r0,[r1] ; Store configuration in Extra Control register CONF + + ; + ; Disable all MPU protections + ; + ldr r1,MPU_CTL_REG ; Load address of MPU_CTL register + ldrh r2,MPU_CTL_RST ; Load reset value of MPU_CTL register + strh r2,[r1] ; Store reset value of MPU_CTL register + + .endif ; CHIPSET = 4 or 6 or 7 or 8 or 10 or 11 or 12 + +; +; Wait-state configuration of external and internal memories +; + .if BOARD = 34 +; +; Wait states for Perseus - see IQ_InitWaitStates for details +; + + + mov r0, #NUM_CS_REGS ; number of chip selects to configure + ldr r1, addrCS0 ; first CS register + ldr r2, CSConfigTable ; table of values to program + +ConfigCS: + ldrh r3,[r2] + strh r3,[r1] + add r1, r1, #2 + add r2, r2, #2 + sub r0, r0, #1 + cmp r0, #0 + bne ConfigCS + + bl Ensure_external_access + bl Copy_code_into_CS7 + bl Toggle_nIBoot + +; Wait a while - not quite sure why, but it is required for Avenger II + mov r0,#0x100 +WaitAWhile2: + sub r0, r0, #1 + cmp r0, #0 + bne WaitAWhile2 + + bl Clear_Internal_SRAM ; This is required if the BSS is not in SRAM + + .elseif BOARD = 35 + + ldr r1,addrCS0 + ldrh r2,CS0_MEM_REG ; CS0 initialization + strh r2,[r1] + ldrh r2,CS1_MEM_REG ; CS1 initialization + strh r2,[r1,#0x2] + ldrh r2,CS2_MEM_REG ; CS2 initialization + strh r2,[r1,#0x4] + ldrh r2,CS7_MEM_REG ; CS7 initialization + strh r2,[r1,#0x8] + ldrh r2,CS6_MEM_REG ; CS6 initialization + strh r2,[r1,#0xC] + mov r2,#API_ADAPT ; API-RHEA configuration + strh r2,[r1,#0xE] + + bl Ensure_external_access + bl Copy_code_into_CS7 + bl Toggle_nIBoot + bl Clear_Internal_SRAM ; This is required if the BSS is not in SRAM + + .else + + ldr r1,addrCS0 + .if CHIPSET != 12 + ldrh r2,CS0_MEM_REG ; ROM initialization + strh r2,[r1] ; CS0 + + ldrh r2,CS1_MEM_REG ; RAM Initialization + strh r2,[r1,#2] ; CS1 + + ldrh r2,CS2_MEM_REG ; RAM Initialization + strh r2,[r1,#4] ; CS2 + + ldrh r2,CS3_MEM_REG ; Parallel I/O on B-Sample + strh r2,[r1,#6] ; CS3 (unused on EVA4?) + + ldrh r2,CS4_MEM_REG ; Latch on B-Sample + strh r2,[r1,#0xa] ; CS4 (unused on EVA4) + + .else + + ldrh r2,CS0_MEM_REG ; CALYPSO PLUS TEST MODE - TO BE ERASED - FLASH Initialization + strh r2,[r1,#0x0] ; CS0 + + ldrh r2,CS5_MEM_REG ; FLASH Initialization + strh r2,[r1,#0xA] ; CS5 + + ldrh r2,CS4_MEM_REG ; RAM Initialization + strh r2,[r1,#0x8] ; CS4 + + .endif + + .if CHIPSET = 3 + ldrh r2,CS6_MEM_REG ; Internal SRAM initialization + strh r2,[r1,#0xc] ; CS6 Internal RAM + + .elseif CHIPSET = 4 + ldrh r2,CS6_MEM_REG ; Internal SRAM initialization + strh r2,[r1,#0xc] ; CS6 Internal RAM + + ldrh r2,CS7_MEM_REG ; Internal SRAM initialization + strh r2,[r1,#0x8] ; CS7 Internal Boot RAM + + .elseif CHIPSET = 5 + ldrh r2,CS6_MEM_REG ; Internal SRAM initialization + strh r2,[r1,#0xc] ; CS6 Internal RAM + + .elseif CHIPSET = 6 + ldrh r2,CS6_MEM_REG ; Internal SRAM initialization + strh r2,[r1,#0xc] ; CS6 Internal RAM + + .elseif CHIPSET = 7 + ldrh r2,CS6_MEM_REG ; Internal SRAM initialization + strh r2,[r1,#0xc] ; CS6 Internal RAM + + ldrh r2,CS7_MEM_REG ; Internal SRAM initialization + strh r2,[r1,#0x8] ; CS7 Internal Boot ROM + + .elseif CHIPSET = 8 + ldrh r2,CS6_MEM_REG ; Internal SRAM initialization + strh r2,[r1,#0xc] ; CS6 Internal RAM + + ldrh r2,CS7_MEM_REG ; Internal SRAM initialization + strh r2,[r1,#0x8] ; CS7 Internal Boot ROM + + .elseif CHIPSET = 10 + ldrh r2,CS6_MEM_REG ; Internal SRAM initialization + strh r2,[r1,#0xc] ; CS6 Internal RAM + + ldrh r2,CS7_MEM_REG ; Internal SRAM initialization + strh r2,[r1,#0x8] ; CS7 Internal Boot ROM + + .elseif CHIPSET = 11 + ldrh r2,CS6_MEM_REG ; Internal SRAM initialization + strh r2,[r1,#0xc] ; CS6 Internal RAM + + ldrh r2,CS7_MEM_REG ; Internal SRAM initialization + strh r2,[r1,#0x8] ; CS7 Internal Boot ROM + .endif ; CHIPSET = 3 or 4 or 5 or 6 or 7 or 8 or 10 or 11 + + ldrh r2,CTL_MEM_REG ; API-RHEA configuration + strh r2,[r1,#0xe] + + .endif ; BOARD = 34 | 35 + + .if BOARD = 40 | 41 +; /* On D-Sample Board, use A22 mode (ADD(22) instead of CS4) to be able to +; address 8 Mbytes especially with CS0 (Flash) & CS3 (External Peripherals) */ + ldr r1,EX_MPU_CONF_REG + ldrh r2,[r1] + ldr r0,EX_FLASH_VALUE + orr r0, r0, r2 + strh r0,[r1] + .endif + +; +; /* Insure that the processor is in supervisor mode. */ +; + MRS a1,CPSR ; Pickup current CPSR + BIC a1,a1,#MODE_MASK ; Clear the mode bits + ORR a1,a1,#SUP_MODE ; Set the supervisor mode bits + ORR a1,a1,#LOCKOUT ; Insure IRQ and FIQ interrupts are + ; locked out + MSR CPSR,a1 ; Setup the new CPSR +; + +; +; +; REWORK OF .bss INITIALIZATION - start +; Creation of INT_memset and INT_memcpy, respectively identical to memset and +; memcpy from the rts library of compiler V2.51/2.54. +; They are used to make the initialization of the .bss section and the load +; of the internal ram code not dependent to the 32-bit alignment. +; The old code used for the initialization and the load used a loop with +; 4-byte increment, assuming the 32-bit alignment of the .bss section. +; This alignment is not necessary true. +; +; /* Clear the un-initialized global and static C data areas. */ +; Initialize the system stack pointer a first time to allow use of memset function +; which needs stack. +; The system stack pointers will be fully initialized after having cleared +; the BSS area. */ +; + LDR a1,StackSegment ; Pickup the begining address from .cmd file + ; (is aligned on 8 byte boundary) + + MOV a2,#SYSTEM_SIZE ; Pickup system stack size + SUB a2,a2,#4 ; Subtract one word for first addr + ADD a3,a1,a2 ; Build start of system stack area + + MOV sp,a3 ; Setup initial stack pointer + + STMFD sp!,{a1-a4} ; Save a1-a4 registers to stack + + LDR a1,BSS_Start ; Pickup the start of the BSS area + LDR a3,BSS_End ; Pickup the end of the BSS area + SUB a3,a3,a1 ; Calculate size of the BSS area + MOV a2,#0 ; Clear value in a2 + + BL _INT_memset ; Clear the BSS area using memset function + + .if LONG_JUMP >= 3 ; + LDR a1,BSS_IntMem_Start ; Pickup the start of the BSS area + LDR a3,BSS_IntMem_End ; Pickup the end of the BSS area + SUB a3,a3,a1 ; Calculate size of the BSS area + MOV a2,#0 ; Clear value in a2 + + BL _INT_memset ; Clear the BSS area using memset function + + .endif + + LDMFD sp!,{a1-a4} ; Restore a1-a4 registers from stack + +; REWORK OF .bss INITIALIZATION - end + +; +; /* Setup the vectors loaded flag to indicate to other routines in the +; system whether or not all of the default vectors have been loaded. +; If INT_Loaded_Flag is 1, all of the default vectors have been loaded. +; Otherwise, if INT_Loaded_Flag is 0, registering an LISR cause the +; default vector to be loaded. In the THUMB this variable is always +; set to 1. All vectors must be setup by this function. */ +; INT_Loaded_Flag = 0; +; + MOV a1,#1 ; All vectors are assumed loaded + LDR a2,Loaded_Flag ; Build address of loaded flag + STR a1,[a2,#0] ; Initialize loaded flag +; +; /* Initialize the system stack pointers. This is done after the BSS is +; cleared because the TCD_System_Stack pointer is a BSS variable! It is +; assumed that the .cmd file is written to direct where these stacks should +; be allocated and to align them on double word boundaries. +; + LDR a1,StackSegment ; Pickup the begining address from .cmd file + ; (is aligned on 8 byte boundary) + MOV a2,#SYSTEM_SIZE ; Pickup system stack size + SUB a2,a2,#4 ; Subtract one word for first addr + ADD a3,a1,a2 ; Build start of system stack area + MOV v7,a1 ; Setup initial stack limit + LDR a4,System_Limit ; Pickup system stack limit address + STR v7,[a4, #0] ; Save stack limit + MOV sp,a3 ; Setup initial stack pointer + LDR a4,System_Stack ; Pickup system stack address + STR sp,[a4, #0] ; Save stack pointer + MOV a2,#IRQ_STACK_SIZE ; Pickup IRQ stack size in bytes + ADD a3,a3,a2 ; Allocate IRQ stack area + MRS a1,CPSR ; Pickup current CPSR + BIC a1,a1,#MODE_MASK ; Clear the mode bits + ORR a1,a1,#IRQ_MODE ; Set the IRQ mode bits + MSR CPSR,a1 ; Move to IRQ mode + MOV sp,a3 ; Setup IRQ stack pointer + MOV a2,#FIQ_STACK_SIZE ; Pickup FIQ stack size in bytes + ADD a3,a3,a2 ; Allocate FIQ stack area + MRS a1,CPSR ; Pickup current CPSR + BIC a1,a1,#MODE_MASK ; Clear the mode bits + ORR a1,a1,#FIQ_MODE ; Set the FIQ mode bits + MSR CPSR,a1 ; Move to the FIQ mode + MOV sp,a3 ; Setup FIQ stack pointer + + MRS a1,CPSR ; Pickup current CPSR + BIC a1,a1,#MODE_MASK ; Clear the mode bits + ORR a1,a1,#ABORT_MODE ; Set the Abort mode bits + MSR CPSR,a1 ; Move to the Abort mode + LDR sp,Exception_Stack ; Setup Abort stack pointer + + MRS a1,CPSR ; Pickup current CPSR + BIC a1,a1,#MODE_MASK ; Clear the mode bits + ORR a1,a1,#UNDEF_MODE ; Set the Undefined mode bits + MSR CPSR,a1 ; Move to the Undefined mode + LDR sp,Exception_Stack ; Setup Undefined stack pointer + ; (should never be used) + +; go to Supervisor Mode + MRS a1,CPSR ; Pickup current CPSR + BIC a1,a1,#MODE_MASK ; Clear mode bits + ORR a1,a1,#SUP_MODE ; Set the supervisor mode bits + MSR CPSR,a1 ; All interrupt stacks are setup, + ; return to supervisor mode +; +; /* Define the global data structures that need to be initialized by this +; routine. These structures are used to define the system timer +; management HISR. */ +; TMD_HISR_Stack_Ptr = (VOID *) a3; +; TMD_HISR_Stack_Size = TIMER_SIZE; +; TMD_HISR_Priority = TIMER_PRIORITY; +; +; TMD_HISR_Stack_Ptr points at the top (the lowest address) of the allocated +; area. The Timer HISR (called "SYSTEM H") and its related stack will be created +; in TMI_Initialize(). The current stack pointer will be set at the bottom (the +; lowest address) of the expected area. + + LDR a4,HISR_Stack_Ptr ; Pickup variable's address + ADD a3,a3,#4 ; Increment to next available word + STR a3,[a4, #0] ; Setup timer HISR stack pointer + MOV a2,#TIMER_SIZE ; Pickup the timer HISR stack size + BIC a2,a2,#3 ; Insure word alignment + ADD a3,a3,a2 ; Allocate the timer HISR stack + ; from available memory + LDR a4,HISR_Stack_Size ; Pickup variable's address + STR a2,[a4, #0] ; Setup timer HISR stack size + MOV a2,#TIMER_PRIORITY ; Pickup timer HISR priority (0-2) + LDR a4,HISR_Priority ; Pickup variable's address + STR a2,[a4, #0] ; Setup timer HISR priority + + .if CHIPSET = 12 + ; This sequence must be always done in order to download the interrupt + ; vector remapping + MOV V1, a3 ; Save a3 register + BL _f_load_int_mem ; Download FLASH to Internal RAM + MOV a3, V1 ; Restore a3 register + .else + + .if LONG_JUMP >= 3 + MOV V1, a3 ; Save a3 register + BL _f_load_int_mem ; Download FLASH to Internal RAM + MOV a3, V1 ; Restore a3 register + .endif + + .endif ; CHIPSET != 12 + +; We now fill up the System, IRQ, FIQ and System Timer HISR stacks with 0xFE for +; checking the status of the stacks later. +; inputs: +; a3 still has the bottom of all four stacks and is aligned. +; algorithm: +; We start from the top of all four stacks (*System_Limit), which is +; necessarily aligned. We store 0xFEFEFEFE until we have filled the +; bottom of the fourth stack +; outputs: +; memory has 0xFE on all four stacks: System, FIQ, IRQ and System Timer HISR +; a3 still has the bottom of all four stacks + + LDR a2,System_Limit ; pickup system stack limit address + LDR a1,[a2] ; a1 = StackSegment + MOV a4,#0FEh ; use this and the next 7 instructons to set a4 = 0xFEFEFEFE + STRB a4,[a1, #0] + STRB a4,[a1, #1] + STRB a4,[a1, #2] + STRB a4,[a1, #3] + LDR a4,[a1],#4 ; stored first word, move to second + +fill_stack: + STR a4,[a1],#4 ; store a word and increment by four + CMP a1,a3 ; is this the last address? + BLT fill_stack ; if not, loop back + +; +; Perform auto-initialization. if cinit is -1, then there is none. +; + LDR r0, c_cinit + CMN r0, #1 + BLNE _auto_init +; +; /* Call INC_Initialize with a pointer to the first available memory +; address after the compiler's global data. This memory may be used +; by the application. */ +; INC_Initialize(first_available_memory); +; + MOV a1,a3 ; Pass the first available memory + B _INC_Initialize ; to high-level initialization +;} +; + + + .if BOARD=35 | BOARD=34 + +;/* +; * FUNCTION +; * +; * Ensure_external_access +; */ +Ensure_external_access: + ;AI_ResetBit(4); // request shared mem clock + ldr r1, armio_out + ldrh r2, [r1] + bic r2, r2, #0x10 + strh r2, [r1] + + ;while(AI_ReadBit(5)!=1); // wait for acknowledge +ack: + ldr r1, armio_in + ldrh r2, [r1] + and r2, r2, #0x20 + cmp r2, #0x20 + bne ack + bx lr ; Return to caller + +;/* +; * FUNCTION +; * +; * Copy_code_into_CS7 +; */ +Copy_code_into_CS7: + ldr r1, addrExtraConf + ldr r3, DEF_EXTRA_CONF + strh r3, [r1] ; ensure CS7 selects internal memory + + mov r0, #CS7_SIZE ; size of CS7 memory in bytes + mov r1, #CS7_ADDR ; destination + mov r2, #0 ; source +CopyIntCode: + ldr r3,[r2] + str r3,[r1] + add r1, r1, #4 + add r2, r2, #4 + sub r0, r0, #4 + cmp r0, #0 + bne CopyIntCode + + ldr r1, addrCS7 + ldr r2, [r1] + bic r2, r2, #0x80 ; Write Enable OFF on CS7 + strh r2, [r1] + bx lr ; Return to caller + +;/* +; * FUNCTION +; * +; * Toggle_nIBoot +; */ +Toggle_nIBoot: + ldr r1, addrExtraConf ; Address of Extra Conf Register + ldr r3, EXTRA_CONF ; set CS7 at address zero + strh r3, [r1] + bx lr ; Return to caller + +;/* +; * FUNCTION +; * +; * Clear_Internal_SRAM +; */ +Clear_Internal_SRAM: + mov r0, #SRAM_ADDR ; r0 points to SRAM start + mov r1, #SRAM_SIZE + add r1, r0, r1 ; r1 points to SRAM end + mov r2, #0 + +ClearSram: + str r2,[r0], #4 + cmp r0, r1 ; done? + bne ClearSram ; no - loop + bx lr ; Return to caller + + .endif ; BOARD=34 | BOARD=35 + +; +;/*************************************************************************/ +;/* */ +;/* FUNCTION */ +;/* */ +;/* INT_Vectors_Loaded */ +;/* */ +;/* DESCRIPTION */ +;/* */ +;/* This function returns the flag that indicates whether or not */ +;/* all the default vectors have been loaded. If it is false, */ +;/* each LISR register also loads the ISR shell into the actual */ +;/* vector table. */ +;/* */ +;/* AUTHOR */ +;/* */ +;/* Barry Sellew, Accelerated Technology, Inc. */ +;/* */ +;/* CALLED BY */ +;/* */ +;/* TCC_Register_LISR Register LISR for vector */ +;/* */ +;/* CALLS */ +;/* */ +;/* None */ +;/* */ +;/* INPUTS */ +;/* */ +;/* None */ +;/* */ +;/* OUTPUTS */ +;/* */ +;/* None */ +;/* */ +;/* HISTORY */ +;/* */ +;/* NAME DATE REMARKS */ +;/* */ +;/* B. Sellew 01-19-1996 Created initial version 1.0 */ +;/* B. Sellew 01-22-1996 Verified version 1.0 */ +;/* */ +;/*************************************************************************/ +;INT INT_Vectors_Loaded(void) +;{ + .def $INT_Vectors_Loaded +$INT_Vectors_Loaded ; Dual-state interworking veneer + .state16 + BX pc + NOP + .state32 + B _INT_Vectors_Loaded +; + .def _INT_Vectors_Loaded +_INT_Vectors_Loaded +; +; /* Just return the loaded vectors flag. */ +; return(INT_Loaded_Flag); +; + MOV a1,#1 ; Always return TRUE since there + ; are really only two normal + ; vectors IRQ & FIQ + BX lr ; Return to caller +;} +; +; +;/*************************************************************************/ +;/* */ +;/* FUNCTION */ +;/* */ +;/* INT_Setup_Vector */ +;/* */ +;/* DESCRIPTION */ +;/* */ +;/* This function sets up the specified vector with the new vector */ +;/* value. The previous vector value is returned to the caller. */ +;/* */ +;/* AUTHOR */ +;/* */ +;/* Barry Sellew, Accelerated Technology, Inc. */ +;/* */ +;/* CALLED BY */ +;/* */ +;/* Application */ +;/* TCC_Register_LISR Register LISR for vector */ +;/* */ +;/* CALLS */ +;/* */ +;/* None */ +;/* */ +;/* INPUTS */ +;/* */ +;/* vector Vector number to setup */ +;/* new Pointer to new assembly */ +;/* language ISR */ +;/* */ +;/* OUTPUTS */ +;/* */ +;/* old vector contents */ +;/* */ +;/* HISTORY */ +;/* */ +;/* NAME DATE REMARKS */ +;/* */ +;/* B. Sellew 01-19-1996 Created initial version 1.0 */ +;/* B. Sellew 01-22-1996 Verified version 1.0 */ +;/* */ +;/*************************************************************************/ +;VOID *INT_Setup_Vector(INT vector, VOID *new) +;{ + .def $INT_Setup_Vector +$INT_Setup_Vector ; Dual-state interworking veneer + .state16 + BX pc + NOP + .state32 + B _INT_Setup_Vector +; + .def _INT_Setup_Vector +_INT_Setup_Vector +; +;VOID *old_vector; /* Old interrupt vector */ +;VOID **vector_table; /* Pointer to vector table */ +; +; /* Calculate the starting address of the actual vector table. */ +; vector_table = (VOID **) 0; +; +; /* Pickup the old interrupt vector. */ +; old_vector = vector_table[vector]; +; +; /* Setup the new interrupt vector. */ +; vector_table[vector] = new; +; +; /* Return the old interrupt vector. */ +; return(old_vector); +; + MOV a1,#0 ; This routine is not applicable to + ; THUMB, return a NULL pointer + BX lr ; Return to caller +;} +; +; +; +; +;/*************************************************************************/ +;/* */ +;/* FUNCTIONS */ +;/* */ +;/* INT_EnableIRQ, INT_DisableIRQ */ +;/* */ +;/* DESCRIPTION */ +;/* */ +;/* This function enable/disable IRQ/FIQ in current mode */ +;/* */ +;/*************************************************************************/ +; + .global $INT_EnableIRQ +$INT_EnableIRQ: + .state16 + BX pc + nop + + .state32 + MRS a1, CPSR ; read current PSR + BIC a1,a1,#MODE_MASK ; remove all mode bits + ORR a1,a1,#IRQ_MODE ; retrieve desired mode + MSR CPSR,a1 ; IRQ mode + + MRS a1, CPSR ; read current PSR + BIC a1,a1,#LOCKOUT ; interrupt lockout value + MSR CPSR,a1 ; Lockout interrupts + + BIC a1,a1,#MODE_MASK ; remove all mode bits + ORR a1,a1,#SUP_MODE + MSR CPSR,a1 ; Lockout interrupts + + add a1, pc, #1 ; back to Thumb mode + bx a1 + + .state16 + BX lr ; Return to caller + +; +; + .global $INT_DisableIRQ +$INT_DisableIRQ: + .state16 + BX pc + nop + + .state32 + MRS a1, CPSR ; read current PSR + BIC a1,a1,#MODE_MASK ; remove all mode bits + ORR a1,a1,#IRQ_MODE ; retrieve desired mode + MSR CPSR,a1 ; IRQ mode + + MRS a1, CPSR ; read current PSR + ORR a1,a1,#LOCKOUT ; Build interrupt lockout value + MSR CPSR,a1 ; Lockout interrupts + + BIC a1,a1,#MODE_MASK ; remove all mode bits + ORR a1,a1,#SUP_MODE + MSR CPSR,a1 ; Lockout interrupts + + add a1, pc, #1 ; back to Thumb mode + bx a1 + + .state16 + BX lr ; Return to caller +; +; +;/*************************************************************************/ +;/* */ +;/* FUNCTION */ +;/* */ +;/* INT_Retrieve_Shell */ +;/* */ +;/* DESCRIPTION */ +;/* */ +;/* This function retrieves the pointer to the shell interrupt */ +;/* service routine. The shell interrupt service routine calls */ +;/* the LISR dispatch routine. */ +;/* */ +;/* AUTHOR */ +;/* */ +;/* Barry Sellew, Accelerated Technology, Inc. */ +;/* */ +;/* CALLED BY */ +;/* */ +;/* TCC_Register_LISR Register LISR for vector */ +;/* */ +;/* CALLS */ +;/* */ +;/* None */ +;/* */ +;/* INPUTS */ +;/* */ +;/* vector Vector number to setup */ +;/* */ +;/* OUTPUTS */ +;/* */ +;/* shell pointer */ +;/* */ +;/* HISTORY */ +;/* */ +;/* NAME DATE REMARKS */ +;/* */ +;/* B. Sellew 01-19-1996 Created initial version 1.0 */ +;/* B. Sellew 01-22-1996 Verified version 1.0 */ +;/* */ +;/*************************************************************************/ +;VOID *INT_Retrieve_Shell(INT vector) +;{ + .def $INT_Retrieve_Shell +$INT_Retrieve_Shell ; Dual-state interworking veneer + .state16 + BX pc + NOP + .state32 + B _INT_Retrieve_Shell +; + .def _INT_Retrieve_Shell +_INT_Retrieve_Shell +; +; /* Return the LISR Shell interrupt routine. */ +; return(INT_Vectors[vector]); +; + MOV a1,#0 ; This routine is not applicable to + ; THUMB, return a NULL pointer + BX lr ; Return to caller +;} +; +; +; +;/* The following section contains default interrupt handlers. */ +; + .if TI_NUC_MONITOR = 1 +; define a new section to be mapped independently + .sect ".irqtext" + + .def _INT_IRQ + .global _INT_IRQ +_INT_IRQ + .else + .def INT_IRQ +INT_IRQ + .endif + +; +; /* Call Prepare for IRQ interrupt processing by calling +; TCT_Interrupt_Context_Save. */ + STMDB sp!,{a1-a4} ; Save a1-a4 on temporary IRQ stack + +;BUG correction 1st part ------------------- +;It looks like there is an issue with ARM7 IRQ masking in the CPSR register +;which leads to crashes in Nucleus+ scheduler. +;Basically the code below (correct as LOCKOUT = 0xC0) is used in many places by N+ but do not +;prevent from having an interrupt after the execution of the third line (I mean execution, not +;fetch). +; MRS a1,CPSR ; Pickup current CPSR +; ORR a1,a1,#LOCKOUT ; Build interrupt lockout value +; MSR CPSR,a1 ; Lockout interrupts +; * IRQ INTERRUPT ! * +; Next instructions... +; +;SW workaround: +;When a task is interrupted at this point an interrupted context is stored on its task and will +;be resumed later on at the next instruction but to make a long story short it leads to some +;problem as the OS does not expect to be interrupted there. +;Further testing tends to show that the CPSR *seems* to be loaded with the proper masking value +;but that the IRQ is still triggered (has been hardwarewise requested during the instruction +;exectution by the ARM7 core?) + MRS a1,spsr ; check for the IRQ bug: + TST a1,#080h ; if the I - flag is set, + BNE IRQBUG ; then postpone execution of this IRQ +;Bug correction 1st part end --------------- + + SUB a4,lr,#4 ; Save IRQ's lr (return address) + BL _TCT_Interrupt_Context_Save ; Call context save routine + + .if TI_NUC_MONITOR = 1 +; Log the IRQ call entry + .global _ti_nuc_monitor_LISR_log + BL _ti_nuc_monitor_LISR_log ; Call the LISR Log function. + .endif + +; +; /* On actuall hardware, a register must be examined to see what the +; IRQ interrupt was caused from. For default processing, the +; timer is the only IRQ interrupt source. It is assumed that further +; timer interrupts are disabled upon this call. */ +; + BL _IQ_IRQ_isr ; Call int. service routine + + .if TI_NUC_MONITOR = 1 +; Log the IRQ exit + .global _ti_nuc_monitor_LISR_log_end + BL _ti_nuc_monitor_LISR_log_end ; Call the LISR end function. + .endif + +; +; /* IRQ interrupt processing is complete. Restore context- Never +; returns! */ + B _TCT_Interrupt_Context_Restore + +;BUG correction 2nd part ------------------ +IRQBUG: LDMFD sp!,{a1-a4} ; return from interrupt + SUBS pc,r14,#4 +;BUG correction 2nd part end -------------- + +; + .if TI_NUC_MONITOR = 1 + .sect ".inttext" + .endif +; + .if TI_PROFILER = 1 +; define a new section to be mapped independently + .sect ".fiqtext" + + .def _INT_FIQ + .global _INT_FIQ +_INT_FIQ + .else + .def INT_FIQ +INT_FIQ + .endif + + .if TI_PROFILER = 1 +; Warning : +; This code has been added for profiliing purpose. +; It removes all other FIQ. + .global _ti_profiler_handler +; Timing profiler using FIQ - Handle FIQ directly here + STMFD sp!,{R0-R4, LR} ; Save R0-R4 and LR on FIQ stack + + MOV R0, LR ; Retrieve link register in R0 + BL _ti_profiler_handler ; Store into buffer + BL _IQ_FIQ_isr ; Call the FIQ ISR + LDMFD sp!,{R0-R4, LR} ; Restore R0-R4 and LR from FIQ stack + SUBS PC, LR, #4 ; return from FIQ + .else + +; +; /* Call Prepare for FIQ interrupt processing by calling +; TCT_Interrupt_Context_Save. */ + STMDB sp!,{a1-a4} ; Save a1-a4 on temporary FIQ stack + SUB a4,lr,#4 ; Save FIQ's lr (return address) + BL _TCT_Interrupt_Context_Save ; Call context save routine +; +; /* On actuall hardware, a register must be examined to see what the +; FIQ interrupt was caused from. For default processing, the +; test is the only FIQ interrupt source. */ +; +; /* Replace this with a call to your own ISR */ + BL _IQ_FIQ_isr ; Call the FIQ ISR + +; +; /* FIQ interrupt processing is complete. Restore context- Never +; returns! */ + B _TCT_Interrupt_Context_Restore + + .endif + + .if TI_PROFILER = 1 + .sect ".inttext" + .endif + +;*************************************************************** +;* CONSTANT TABLE * +;*************************************************************** + +; +; /* Define all the global addresses used in this section */ +; + +; internal/external RAM + .if CHIPSET = 3 | CHIPSET = 5 | CHIPSET = 6 +RAM_SIZE .equ 0x40000 ; size (in bytes) of internal RAM +RAM_LOW .equ 0x3000000 ; first address of internal RAM + .elseif CHIPSET = 4 +RAM_SIZE .equ 0x40000 ; size (in bytes) of internal RAM +RAM_LOW .equ 0x800000 ; first address of internal RAM + .elseif CHIPSET = 7 | CHIPSET = 8 | CHIPSET = 10 | CHIPSET = 11 | CHIPSET = 12 + .if L1_GPRS = 1 +RAM_SIZE .equ 0x200000 ; size (in bytes) of external RAM +RAM_LOW .equ 0x1000000 ; first address of external RAM + .else ; GSM ONLY +RAM_SIZE .equ 0x80000 ; size (in bytes) of internal RAM +RAM_LOW .equ 0x800000 ; first address of internal RAM + .endif + .endif + +RAM_HIGH .equ RAM_LOW + RAM_SIZE ; first address after internal/external RAM + + + .global exception_stack ; top address of SVC mode stack + + .global _xdump_buffer ; first address of state data + + .global stack_segment ; address of the top of the system stack + +; +; /* Define exception functions */ +; + .ref _dar_exception + +XDUMP_STACK_SIZE .equ 20 + +; layout of xdump buffer: +; struct xdump_s { +; long registers[16] // svc mode registers +; long cpsr // svc mode CPSR +; long exception // magic word + index of vector taken +; long stack[20] // bottom 20 words of usr mode stack +; } + +arm_undefined: + stmfd r13!,{r11,r12} ; store r12 for Xdump_buffer pointer, r11 for index + mov r11,#1 + b save_regs + +arm_swi: + stmfd r13!,{r11,r12} ; store r12 for Xdump_buffer pointer, r11 for index + mov r11,#2 + b save_regs + +arm_abort_prefetch: + stmfd r13!,{r11,r12} ; store r12 for Xdump_buffer pointer, r11 for index + mov r11,#3 + b save_regs + + +arm_abort_data: + stmfd r13!,{r11,r12} ; store r12 for Xdump_buffer pointer, r11 for index + mov r11,#4 + b save_regs + +arm_reserved: + ldr r13,Exception_Stack ; should never happen, but mode is unknown at this point + stmfd r13!,{r11,r12} ; store r12 for Xdump_buffer pointer, r11 for index + mov r11,#5 + b save_regs + +save_regs: + ldr r12,Xdump_buffer + str r14,[r12,#4*15] ; save r14_abt (original PC) into r15 slot + + stmia r12,{r0-r10} ; save unbanked registers (except r11 and r12) + ldmfd r13!,{r0,r1} ; get original r11 and r12 + str r0,[r12,#4*11] ; save original r11 + str r1,[r12,#4*12] ; save original r12 + mrs r0,spsr ; get original psr + str r0,[r12,#4*16] ; save original cpsr + + mrs r1,cpsr ; save mode psr + bic r2,r1,#0x1f ; psr with mode bits cleared + and r0,r0,#0x1f ; get original mode bits + add r0,r0,r2 + + msr cpsr,r0 ; move to pre-exception mode + str r13,[r12,#4*13] ; save original SP + str r14,[r12,#4*14] ; save original LR + msr cpsr,r1 ; restore mode psr + + ; r11 has original index + orr r10,r11,#0xDE<<24; r10 = 0xDEAD0000 + index of vector taken + orr r10,r10,#0xAD<<16 + str r10,[r12,#4*17] ; save magic + index + + mov r0,r11 ; put index into 1st argument + b _dar_exception + + .global $exception ; export function + +$exception: ; Veneer function + .ref _exception + .state16 + adr r0,_exception + bx r0 + .align + .state32 + .def _exception +_exception: + ldr r12,Xdump_buffer ; redundant unless _exception is called + ldr r11,[r12,#4*13] ; get svc mode r13 + add r12,r12,#4*18 ; base of stack buffer + + ; check if svc r13(sp) is within internal/external RAM. It *could* be invalid. + ; we boldly assume stack is only within internal RAM except for GPRS build on + ; Calypso chipset : stack is within external RAM + .if CHIPSET = 7 | CHIPSET = 8 | CHIPSET = 10 | CHIPSET = 11 + .if L1_GPRS = 1 + ; if GPRS, check for internal RAM as well as 2Mbytes of external RAM + cmp r11,#0x800000 ; INTERNAL RAM_LOW + blt nostack + mov r0, #0x880000 ; INTERNAL RAM_HIGH + sub r0,r0,#XDUMP_STACK_SIZE + cmp r11,r0 + blt stack_range + ; was not less than 0x880000, so check for external RAM + cmp r11,#RAM_LOW + blt nostack + mov r0,#RAM_HIGH + sub r0,r0,#XDUMP_STACK_SIZE + cmp r11,r0 + bge nostack + .else ; GSM ONLY + cmp r11,#RAM_LOW + blt nostack + mov r0,#RAM_HIGH + sub r0,r0,#XDUMP_STACK_SIZE + cmp r11,r0 + bge nostack + .endif + .endif + +stack_range: + ldmfd r11!,{r0-r9} ; copy ten stack words.. + stmia r12!,{r0-r9} + ldmfd r11!,{r0-r9} ; copy ten stack words.. + stmia r12!,{r0-r9} + +nostack: +STACKS .equ SYSTEM_SIZE + IRQ_STACK_SIZE + FIQ_STACK_SIZE + TIMER_SIZE + .ref _dar_reset + ; we're finished saving all state. Now execute C code for more flexibility. + ; set up a stack for this C call + LDR a1,StackSegment ; Pickup the begining address from .cmd file + ; (is aligned on 8 byte boundary) + MOV a2,#STACKS ; Pickup all stacks size + ADD a2,a2,#0x80 ; Add 128 to get past all used data + ADD a3,a1,a2 + MOV sp,a3 ; Setup exception stack pointer + b _dar_reset + + +BSS_Start + .word .bss +; +BSS_End + .word end +; + .if LONG_JUMP >= 3 + .align 4 +BSS_IntMem_Start: .field _S_D_Mem,32 + .align 4 +BSS_IntMem_End: .field _E_D_Mem,32 + .endif + +StackSegment + .word stack_segment +; +Loaded_Flag + .word _INT_Loaded_Flag +; +System_Limit + .word _TCT_System_Limit +; +System_Stack + .word _TCD_System_Stack +; +HISR_Stack_Ptr + .word _TMD_HISR_Stack_Ptr +; +HISR_Stack_Size + .word _TMD_HISR_Stack_Size +; +HISR_Priority + .word _TMD_HISR_Priority +; +Exception_Stack + .word exception_stack +; +Xdump_buffer + .word _xdump_buffer +; +; The following code is pulled from rts.src, which is part of the +; TI tools installation. +; +;*************************************************************************** +;* PROCESS INITIALIZATION TABLE. +;* +;* THE TABLE CONSISTS OF A SEQUENCE OF RECORDS OF THE FOLLOWING FORMAT: +;* +;* .word <length of data (bytes)> +;* .word <address of variable to initialize> +;* .word <data> +;* +;* THE INITIALIZATION TABLE IS TERMINATED WITH A ZERO LENGTH RECORD. +;* +;*************************************************************************** +;****auto_init(register int *table) +;****{ +;**** register int length; +;**** register int *addr; +;**** +;**** while (length = *table++) +;**** { +;**** addr = (int *)*table++; +;**** while (length) +;**** { +;**** if (length > 3) +;**** { +;**** *addr++ = *table++; +;**** length -= 4; +;**** } +;**** else +;**** { +;**** *(char *)addr++ = *(char *)table++; +;**** length--; +;**** } +;**** } +;**** } +;****} + +tbl_addr: .set R0 +var_addr: .set R1 +length: .set R3 +data: .set R4 + +_auto_init: + B rec_chk + +record: + ;*------------------------------------------------------ + ;* PROCESS AN INITIALIZATION RECORD + ;*------------------------------------------------------ + LDR var_addr, [tbl_addr], #4 + +copy: + ;*------------------------------------------------------ + ;* COPY THE INITIALIZATION DATA + ;*------------------------------------------------------ + CMP length, #3 + + LDRHI data, [tbl_addr], #4 + STRHI data, [var_addr], #4 ; COPY A WORD OF DATA + SUBHI length, length, #4 ; OR ... + LDRLSB data, [tbl_addr], #1 ; + STRLSB data, [var_addr], #1 ; COPY A BYTE OF DATA + SUBLS length, length, #1 + + CMP length, #0 ; CONTINUE TO COPY IF + BNE copy ; LENGTH IS NONZERO + + ANDS length, tbl_addr, #0x3 ; MAKE SURE THE ADDRESS + RSBNE length, length, #0x4 ; IS WORD ALIGNED + ADDNE tbl_addr, tbl_addr, length ; + +rec_chk:LDR length, [tbl_addr], #4 ; PROCESS NEXT + CMP length, #0 ; RECORD IF LENGTH IS + BNE record ; NONZERO + + MOV PC, LR +; + +; +; Creation of INT_memset and INT_memcpy, respectively identical to memset and +; memcpy from the rts library of compiler 2.51/2.54. +; They are used to make the initialization of the .bss section and the load +; of the internal ram code not dependent to the 32-bit alignment. +; The old code used for the initialization and the load used a loop with +; 4-byte increment, assuming the 32-bit alignment of the .bss section. +; This alignment is not necessary true. +; +;****************************************************************************** +;* INT_memset - INITIALIZE MEMORY WITH VALUE * +;****************************************************************************** +;* MEMSET32.ASM - 32 BIT STATE - v2.51 * +;* Copyright (c) 1996-2003 Texas Instruments Incorporated * +;****************************************************************************** + +;**************************************************************************** +;* INT_memset - INITIALIZE MEMORY WITH VALUE. +;* +;* Same memset defined in rts.src. +;* Used in INT_Initialize to clear bss area. +;* Used in f_load_int_mem() function to clear internal memory space used +;* for data and code. +;* The memset function defined in rts library is loaded into internal memory, +;* then, it can not be used in either INT_Initialize, or f_load_int_mem(). +;* +;* C Prototype : void *INT_memset(void *s, int c, size_t n); +;* C++ Prototype : void *std::INT_memset(void *s, int c, std::size_t n); +;* +;**************************************************************************** +;* +;* o DESTINATION LOCATION IS IN r0 +;* o INITIALIZATION VALUE IS IN r1 +;* o NUMBER OF BYTES TO INITIALIZE IS IN r2 +;* +;* o ORIGINAL DESTINATION LOCATION RETURNED IN r0 +;**************************************************************************** + .state32 + .def _INT_memset + +_INT_memset: + STMFD SP!, {R0, LR} ; save R0 also since original dst + ; address is returned. + + TST R0, #3 ; check for word alignment + BEQ _word_aligned + + CMP R2, #0 ; set bytes until there are no more + ; to set or until address is aligned +_unaligned_loop: + STRHIB R1, [R0], #1 + SUBHIS R2, R2, #1 + TSTHI R0, #3 + BNE _unaligned_loop + + CMP R2, #0 ; return early if no more bytes + LDMEQFD SP!, {R0, PC} ; to set. + +_word_aligned: + AND R1, R1, #255 ; be safe since prototype has value as + ; as an int rather than unsigned char + + ORR R1, R1, R1, LSL #8 ; replicate byte in 2nd byte of + ; register + + CMP R2,#4 ; are at least 4 bytes being set + BCC _INT_memset3 + + ORR R1, R1, R1, LSL #16 ; replicate byte in upper 2 bytes + ; of register. note that each of + ; the bottom 2 bytes already contain + ; the byte value from above. + + CMP R2,#8 ; are at least 8 bytes being set + BCC _INT_memset7 + + MOV LR,R1 ; copy bits into another register so + ; 8 bytes at a time can be copied. + ; use LR since it is already being + ; saved/restored. + + CMP R2,#16 ; are at least 16 bytes being set + BCC _INT_memset15 + + STMFD SP!, {R4} ; save regs needed by 16 byte copies + + MOV R4, R1 ; copy bits into 2 other registers so + MOV R12, R1 ; 16 bytes at a time can be copied + + SUB R3, R2, #15 ; set up loop count + AND R2, R2, #15 ; determine number of bytes to set + ; after setting 16 byte blocks + +_INT_memset16_loop: ; set blocks of 16 bytes + STMIA R0!, {R1, R4, R12, LR} + SUBS R3, R3, #16 + BHI _INT_memset16_loop + + LDMFD SP!, {R4} ; resotre regs used by 16 byte copies + +_INT_memset15: ; may still be as many as 15 bytes to + ; set. the address in R0 is guaranteed + ; to be word aligned here. + + TST R2, #8 ; are at least 8 bytes being set + STMNEIA R0!, {R1, LR} + + +_INT_memset7: ; may still be as many as 7 bytes to + ; set. the address in R0 is guaranteed + ; to be word aligned here. + + TST R2, #4 ; are at least 4 bytes being set + STRNE R1, [R0], #4 + +_INT_memset3: ; may still be as many as 3 bytes to + ; set. the address in R0 is guaranteed + ; to be word aligned here. + + TST R2, #2 ; are there at least 2 more bytes to + STRNEH R1, [R0], #2 ; set. the address in R0 is guaranteed + ; to be half-word aligned here. + + TST R2, #1 ; is there one remaining byte to set + STRNEB R1, [R0] + + + LDMFD SP!, {R0, PC} ; restore regs and return + + +;****************************************************************************** +;* INT_memcpy - COPY CHARACTERS FROM SOURCE TO DEST * +;****************************************************************************** +;* MEMCPY32.ASM - 32 BIT STATE - v2.51 * +;* Copyright (c) 1996-2003 Texas Instruments Incorporated * +;****************************************************************************** + +;**************************************************************************** +;* INT_memcpy - COPY CHARACTERS FROM SOURCE TO DEST +;* +;* Same as C_MEMCPY defined in rts.src. +;* Used in INT_Initialize to download code into internal memory space. +;* The memcpy function defined in rts library is loaded into internal memory. +;* then, it can not be used in f_load_int_mem(). +;* +;**************************************************************************** +;* +;* o DESTINATION LOCATION IS IN r0 +;* o SOURCE LOCATION IS IN r1 +;* o NUMBER OF CHARACTERS TO BE COPIED IS IN r2 +;**************************************************************************** + .state32 + .def _INT_memcpy + +_INT_memcpy: + CMP r2, #0 ; CHECK FOR n == 0 + BXEQ lr ; + + STMFD sp!, {r0, lr} ; SAVE RETURN VALUE AND ADDRESS + + TST r1, #0x3 ; CHECK ADDRESS ALIGNMENT + BNE _unaln ; IF NOT WORD ALIGNED, HANDLE SPECIALLY + TST r0, #0x3 ; + BNE _saln ; + +_aln: CMP r2, #16 ; CHECK FOR n >= 16 + BCC _l16 ; + + STMFD sp!, {r4} ; + SUB r2, r2, #16 ; +_c16: LDMIA r1!, {r3, r4, r12, lr} ; COPY 16 BYTES + STMIA r0!, {r3, r4, r12, lr} ; + SUBS r2, r2, #16 ; + BCS _c16 ; + LDMFD sp!, {r4} ; + ADDS r2, r2, #16 ; RETURN IF DONE + LDMEQFD sp!, {r0, pc} ; + +_l16: ANDS r3, r2, #0xC ; + BEQ _cp1 ; + BICS r2, r2, #0xC ; + ADR r12, _4line - 16 ; + ADD pc, r12, r3, LSL #2 ; + +_4line: LDR r3, [r1], #4 ; COPY 4 BYTES + STR r3, [r0], #4 ; + LDMEQFD sp!, {r0, pc} ; CHECK FOR n == 0 + B _cp1 ; + + LDMIA r1!, {r3, r12} ; COPY 8 BYTES + STMIA r0!, {r3, r12} ; + LDMEQFD sp!, {r0, pc} ; CHECK FOR n == 0 + B _cp1 ; + + LDMIA r1!, {r3, r12, lr} ; COPY 12 BYTES + STMIA r0!, {r3, r12, lr} ; + LDMEQFD sp!, {r0, pc} ; CHECK FOR n == 0 + +_cp1: SUBS r2, r2, #1 ; + ADRNE r3, _1line - 4 ; SETUP TO COPY 1 - 3 BYTES... + ADDNE pc, r3, r2, LSL #4 ; + +_1line: LDRB r3, [r1], #1 ; COPY 1 BYTE + STRB r3, [r0], #1 ; + LDMFD sp!, {r0, pc} ; + + LDRH r3, [r1], #2 ; COPY 2 BYTES + STRH r3, [r0], #2 ; + LDMFD sp!, {r0, pc} ; + NOP ; + + LDRH r3, [r1], #2 ; COPY 3 BYTES + STRH r3, [r0], #2 ; + LDRB r3, [r1], #1 ; + STRB r3, [r0], #1 ; + LDMFD sp!, {r0, pc} ; + +_unaln: LDRB r3, [r1], #1 ; THE ADDRESSES ARE NOT WORD ALIGNED. + STRB r3, [r0], #1 ; COPY BYTES UNTIL THE SOURCE IS + SUBS r2, r2, #1 ; WORD ALIGNED OR THE COPY SIZE + LDMEQFD sp!, {r0, pc} ; BECOMES ZERO + TST r1, #0x3 ; + BNE _unaln ; + +_saln: TST r0, #0x1 ; IF THE ADDRESSES ARE OFF BY 1 BYTE + BNE _off1 ; JUST BYTE COPY + + TST r0, #0x2 ; IF THE ADDRESSES ARE NOW WORD ALIGNED + BEQ _aln ; GO COPY. ELSE THEY ARE OFF BY 2, SO + ; GO SHORT WORD COPY + +_off2: SUBS r2, r2, #4 ; COPY 2 BYTES AT A TIME... + BCC _c1h ; +_c2: LDR r3, [r1], #4 ; START BY COPYING CHUNKS OF 4, + .if .TMS470_BIG + STRH r3, [r0, #2] ; + MOV r3, r3, LSR #16 ; + STRH r3, [r0], #4 ; + .else + STRH r3, [r0], #4 ; + MOV r3, r3, LSR #16 ; + STRH r3, [r0, #-2] ; + .endif + SUBS r2, r2, #4 ; + BCS _c2 ; + CMN r2, #4 ; + LDMEQFD sp!, {r0, pc} ; + +_c1h: ADDS r2, r2, #2 ; THEN COPY THE ODD BYTES. + LDRCSH r3, [r1], #2 ; + STRCSH r3, [r0], #2 ; + SUBCS r2, r2, #2 ; + ADDS r2, r2, #1 ; + LDRCSB r3, [r1], #1 ; + STRCSB r3, [r0], #1 ; + LDMFD sp!, {r0, pc} ; + +_off1: SUBS r2, r2, #4 ; COPY 1 BYTE AT A TIME... + BCC _c1b ; +_c1: LDR r3, [r1], #4 ; START BY COPYING CHUNKS OF 4, + .if .TMS470_BIG + STRB r3, [r0, #3] ; + MOV r3, r3, LSR #8 ; + STRB r3, [r0, #2] ; + MOV r3, r3, LSR #8 ; + STRB r3, [r0, #1] ; + MOV r3, r3, LSR #8 ; + STRB r3, [r0], #4 ; + .else + STRB r3, [r0], #4 ; + MOV r3, r3, LSR #8 ; + STRB r3, [r0, #-3] ; + MOV r3, r3, LSR #8 ; + STRB r3, [r0, #-2] ; + MOV r3, r3, LSR #8 ; + STRB r3, [r0, #-1] ; + .endif + SUBS r2, r2, #4 ; + BCS _c1 ; + +_c1b: ADDS r2, r2, #4 ; THEN COPY THE ODD BYTES. + LDMEQFD sp!, {r0, pc} ; +_lp1: LDRB r3, [r1], #1 ; + STRB r3, [r0], #1 ; + SUBS r2, r2, #1 ; + BNE _lp1 ; + LDMFD sp!, {r0, pc} ; + + .end +