FreeCalypso > hg > fc-tourmaline
view src/cs/system/main/int.s @ 283:d9e3f3e293ac
etm_audio.c: fix off-by-one error in auw of FIR coefficients
The implementation of auw operation for UL or DL FIR upload
had this bug: the number of 16-bit shortwords copied into the
RVF-allocated temporary buffer was one too many, causing memory
corruption errors. The present change fixes this bug.
author | Mychaela Falconia <falcon@freecalypso.org> |
---|---|
date | Mon, 08 Nov 2021 02:54:04 +0000 |
parents | 4e78acac3d88 |
children |
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