FreeCalypso > hg > fc-magnetite
view src/cs/system/main/int.s @ 632:d968a3216ba0
new tangomdm build target
TCS211/Magnetite built for target leonardo runs just fine on the Tango-based
Caramel board, but a more proper tangomdm build target is preferable in order
to better market these Tango modems to prospective commercial customers. The
only differences are in GPIO and MCSI config:
* MCSI is enabled in the tangomdm build config.
* GPIO 1 is loudspeaker amplifier control on Leonardo, but on Tango platforms
it can be used for anything. On Caramel boards this GPIO should be
configured as an output driving high.
* GPIO 2 needs to be configured as Calypso input on Leonardo, but on Tango
platforms it can be used for anything. On Caramel boards this GPIO should be
configured as an output, either high or low is OK.
author | Mychaela Falconia <falcon@freecalypso.org> |
---|---|
date | Sat, 04 Jan 2020 19:27:41 +0000 |
parents | ae18f9aad7ce |
children | 8cf3029429f3 |
line wrap: on
line source
;****************************************************************************** ; 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