view src/cs/system/main/gcc/exceptions.S @ 303:f76436d19a7a default tip

!GPRS config: fix long-standing AT+COPS chance hanging bug There has been a long-standing bug in FreeCalypso going back years: sometimes in the AT command bring-up sequence of an ACI-only MS, the AT+COPS command would produce only a power scan followed by cessation of protocol stack activity (only L1 ADC traces), instead of the expected network search sequence. This behaviour was seen in different FC firmware versions going back to Citrine, and seemed to follow some law of chance, not reliably repeatable. This bug has been tracked down and found to be specific to !GPRS configuration, stemming from our TCS2/TCS3 hybrid and reconstruction of !GPRS support that was bitrotten in TCS3.2/LoCosto version. ACI module psa_mms.c, needed only for !GPRS, was missing in the TCS3 version and had to be pulled from TCS2 - but as it turns out, there is a new field in the MMR_REG_REQ primitive that needs to be set correctly, and that psa_mms.c module is the place where this initialization needed to be added.
author Mychaela Falconia <falcon@freecalypso.org>
date Thu, 08 Jun 2023 08:23:37 +0000
parents 4e78acac3d88
children
line wrap: on
line source

/*
 * This module contains ARM exception handlers which used to be
 * in chipsetsw/system/Main/int.s in TI's original version.
 */

	.text
	.code	32

@ 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
@ }

	.globl	_arm_undefined
_arm_undefined:
	@ store r12 for Xdump_buffer pointer, r11 for index
	stmfd   r13!,{r11,r12}
	mov     r11,#1
	b       save_regs

	.globl	_arm_swi
_arm_swi:
	@ store r12 for Xdump_buffer pointer, r11 for index
	stmfd   r13!,{r11,r12}
	mov     r11,#2
	b       save_regs

	.globl	_arm_abort_prefetch
_arm_abort_prefetch:
	@ store r12 for Xdump_buffer pointer, r11 for index
	stmfd   r13!,{r11,r12}
	mov     r11,#3
	b       save_regs

	.globl	_arm_abort_data
_arm_abort_data:
	@ store r12 for Xdump_buffer pointer, r11 for index
	stmfd   r13!,{r11,r12}
	mov     r11,#4
	b       save_regs

	.globl	_arm_reserved
_arm_reserved:
	ldr	r13,=_Except_Stack_SP	@ mode unknown
	@ store r12 for Xdump_buffer pointer, r11 for index
	stmfd   r13!,{r11,r12}
	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

@ the second part

/*
 * For the SP-in-RAM validity check, we use the following simplification:
 * it doesn't really matter what the actual IRAM and XRAM sizes are on
 * any given target, as the address decoder hooked up to the ARM7TDMI core
 * always decodes the full 8 MiB address range for each, causing the
 * actual memories to be aliased multiple times in those two ranges.
 * Furthermore, the XRAM address range falls right after the IRAM one,
 * thus we can get away with only a single range check.
 */

#define	RAM_LOW		0x00800000
#define	RAM_HIGH	0x01800000

#define	XDUMP_STACK_SIZE	20

	.globl	exception
exception:
        ldr     r12,=xdump_buffer
        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.
        cmp     r11,#RAM_LOW
        blt     nostack
        mov     r0,#RAM_HIGH
        sub     r0,r0,#XDUMP_STACK_SIZE
        cmp     r11,r0
        bge     nostack

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:
	@ we're finished saving all state.
	@ Now execute C code for more flexibility.
	@ set up a stack for this C call
	ldr	sp,=_Stack_segment_end
	b	dar_reset