FreeCalypso > hg > fc-tourmaline
view src/cs/layer1/cfile/l1_small.c @ 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
#include "l1sw.cfg" #if (OP_L1_STANDALONE == 0) #include "debug.cfg" #include "rv_swe.h" #endif #if (OP_L1_STANDALONE == 1) #include "general.h" #endif #include "l1_macro.h" #include "l1_confg.h" #if (CODE_VERSION == SIMULATION) #include <string.h> #include "l1_types.h" #include "sys_types.h" #include "l1_const.h" #include "l1_time.h" #if TESTMODE #include "l1tm_defty.h" #endif #if (AUDIO_TASK == 1) #include "l1audio_const.h" #include "l1audio_cust.h" #include "l1audio_defty.h" #endif #if (L1_GTT == 1) #include "l1gtt_const.h" #include "l1gtt_defty.h" #endif #if (L1_MP3 == 1) #include "l1mp3_defty.h" #endif #if (L1_MIDI == 1) #include "l1midi_defty.h" #endif #if (L1_AAC == 1) #include "l1aac_defty.h" #endif #include "l1_defty.h" #include "l1_varex.h" #include "cust_os.h" #include "l1_msgty.h" #include <stdio.h> #include "sim_cfg.h" #include "sim_cons.h" #include "sim_def.h" #include "sim_var.h" #else #include <string.h> #include "l1_types.h" #include "sys_types.h" #include "l1_const.h" #include "l1_time.h" #if TESTMODE #include "l1tm_defty.h" #endif #if (AUDIO_TASK == 1) #include "l1audio_const.h" #include "l1audio_cust.h" #include "l1audio_defty.h" #endif #if (L1_GTT == 1) #include "l1gtt_const.h" #include "l1gtt_defty.h" #endif #if (L1_MP3 == 1) #include "l1mp3_defty.h" #endif #if (L1_MIDI == 1) #include "l1midi_defty.h" #endif #if (L1_AAC == 1) #include "l1aac_defty.h" #endif #include "l1_defty.h" #include "l1_varex.h" #include "cust_os.h" #include "l1_msgty.h" #include "tpudrv.h" #endif #if (W_A_CALYPSO_PLUS_SPR_19599 == 1) #include "sys_memif.h" #endif #if (CHIPSET == 15) #include "sys_inth.h" #include "bspI2c.h" #include "clkm.h" // This could be removed if i2c_pwr_interface is functional extern volatile Bool bspI2c_busLocked[BSP_I2C_NUM_DEVICES] ; #endif #ifndef __GNUC__ /* NEW COMPILER MANAGEMENT * With compiler V3.00, the .text section must be explicitely * defined. * Else the following code will be put in the .cinit section. * The change is applied to all compilers. */ asm(" .sect \".text\" "); #endif UWORD8 *mode_authorized = &(l1s.pw_mgr.mode_authorized); UWORD8 *switch_PWR_MNGT = &(l1_config.pwr_mngt); #if (W_A_CALYPSO_BUG_01435 == 1) asm("SMALL_SLEEP .equ 01h"); asm("BIG_SLEEP .equ 02h"); asm("DEEP_SLEEP .equ 03h"); void f_arm_sleep_cmd(UWORD8 d_sleep_mode) { asm(" LDR R3, MPU_FREE_REG"); // here below the C code: // if ((d_sleep_mode == SMALL_SLEEP) || (d_sleep_mode == BIG_SLEEP)) // * (volatile UWORD16 *) 0xfffffd00 &= 0xfffe; // else // if (d_sleep_mode == DEEP_SLEEP) // * (volatile UWORD16 *) 0xfffffd00 &= 0xefff; asm(" CMP R0, #SMALL_SLEEP"); asm(" BEQ Small_or_Big_Sleep"); asm(" CMP R0, #BIG_SLEEP"); asm(" BEQ Small_or_Big_Sleep"); asm(" CMP R0, #DEEP_SLEEP"); asm(" BXNE LR"); asm("Deep_Sleep: "); asm(" LDR R0, CLKM_CNTL_ARM_CLK_REG"); asm(" LDRH R12, [R0, #0]"); asm(" AND R1, R12, #255"); asm(" AND R12, R12, #61184"); asm(" ORR R12, R1, R12"); asm(" STRH R12, [R0, #0]"); asm(" STMIA R3!, {R4-R7}"); asm(" B End_Sleep"); asm("Small_or_Big_Sleep: "); asm(" LDR R12, CLKM_CNTL_ARM_CLK_REG"); asm(" LDRH R0, [R12, #0]"); asm(" MOV R0, R0, LSL #16"); asm(" MOV R0, R0, LSR #17"); asm(" MOV R0, R0, LSL #1"); asm(" STRH R0, [R12, #0]"); asm(" STMIA R3!, {R4-R7}"); asm("End_Sleep: "); } /* f_arm_sleep_cmd() */ asm("MPU_FREE_REG .word 0xffffff20"); asm("CLKM_CNTL_ARM_CLK_REG .word 0xfffffd00"); #endif #if (CHIPSET == 15) void init_small_sleep() { /* Should not disable bridge_clk during small sleep when an I2C transaction is pending In Locosto without BRIDGE_CLK, I2C interrupt is not generated */ // This could be removed if i2c_pwr_interface is functional Uint8 sts=0, camera_sts = 0; sts=i2c_pwr_interface(0); #ifdef RVM_CAMD_SWE #if(LOCOSTO_LITE == 0) #if (OP_L1_STANDALONE == 0) camera_sts = camera_pwr_interface(0); #endif #endif #endif if (sts != 0 #if(LOCOSTO_LITE == 0) || camera_sts != 0 #endif ) { sts=i2c_pwr_interface(2);//enable *((volatile UINT16 *) CLKM_CNTL_CLK) &= ~CLKM_BRIDGE_DIS; } else { sts=i2c_pwr_interface(1);//disable *((volatile UINT16 *) CLKM_CNTL_CLK) |= CLKM_BRIDGE_DIS; F_INTH_ENABLE_ONE_IT(C_INTH_UART_WAKEUP_IT); } } void exit_small_sleep() { i2c_pwr_interface(2); return; } #endif /*-------------------------------------------------------*/ /* INT_Small_Sleep() */ /*-------------------------------------------------------*/ /* */ /* Description: small sleep */ /* ------------ */ /* Called by TCT_Schedule main loop of Nucleus */ /*-------------------------------------------------------*/ #ifndef __GNUC__ asm(" .def INT_Small_Sleep "); asm("INT_Small_Sleep "); /* NEW COMPILER MANAGEMENT * _switch_PWR_MNGT and _mode_authorized must be .def and not .ref * as they are both defined in this file. */ asm(" .def _switch_PWR_MNGT "); asm(" .def _mode_authorized "); asm("SMALL_SLEEP .equ 01h "); asm("ALL_SLEEP .equ 04h "); asm("BIG_SMALL_SLEEP .equ 05h "); asm("PWR_MNGT .equ 01h "); #if (OP_L1_STANDALONE == 0) // This code log the number of time the Small sleep // function has been invoked #if (TI_PROFILER == 1) asm(" ldr r0, profiler_counter "); // pick counter asm(" mov r1,#0 "); asm(" str r1,[r0] "); #endif #if (TI_NUC_MONITOR == 1) // Push registers on statck because R3 and R4 must not be modified asm(" STMFD sp!,{r0-r5}"); asm(" .global _ti_nuc_monitor_sleep "); asm(" BL _ti_nuc_monitor_sleep"); asm(" LDMFD sp!,{r0-r5}"); #endif // End log call #endif // OP_L1_STANDALONE //asm(" .ref TCT_Schedule_Loop "); //asm(" B TCT_Schedule_Loop "); asm(" ldr r0,Switch "); // pick up sleep mode asm(" ldr r0,[r0] "); // take the current value of the register asm(" ldrb r1,[r0] "); // take the current value of the register asm(" cmp r1,#PWR_MNGT "); // take the current value of the register asm(" bne End_small_sleep "); asm(" ldr r0,Mode "); // pick up sleep mode asm(" ldr r0,[r0] "); // take the current value of the register asm(" ldrb r1,[r0] "); // take the current value of the register asm(" cmp r1,#SMALL_SLEEP "); // take the current value of the register asm(" beq Small_sleep_ok "); asm(" cmp r1,#ALL_SLEEP "); // take the current value of the register asm(" beq Small_sleep_ok "); asm(" cmp r1,#BIG_SMALL_SLEEP "); asm(" bne End_small_sleep "); asm("Small_sleep_ok "); // ***************************************************** // CQ19599: For Calypso+ chipset, extended page mode // shall be disabled before entering deep sleep and // restored at wake up // ***************************************************** #if (W_A_CALYPSO_PLUS_SPR_19599 == 1) asm(" .ref _f_memif_extended_page_mode_read_bit "); asm(" .ref _f_memif_extended_page_mode_disable "); asm(" BL _f_memif_extended_page_mode_read_bit"); //read state of extended page mode asm(" STMFD sp!,{r2}"); //save r2 in stack in case it was used before asm(" MOV r2,r0"); //store the state in r2 asm(" BL _f_memif_extended_page_mode_disable"); //disable extended page mode #endif #if (CHIPSET == 15) //// Disable IRQs asm(" MRS r1, CPSR "); // asm(" MOV r2,r1"); // Copy the contents on CPSR register to r2 asm(" STMFD sp!,{r1}"); // Push r2 in the stack asm(" ORR r1,r1,#00c0h "); // Disable IRQs asm(" MSR CPSR,r1 "); asm(" .ref _init_small_sleep"); asm(" BL _init_small_sleep"); #endif // ***************************************************** //reset the DEEP_SLEEP bit 12 of CNTL_ARM_CLK register // (Cf BUG_1278) asm(" ldr r0,addrCLKM "); // pick up CNTL_ARM_CLK register address asm(" ldrh r1,[r0] "); // take the current value of the register asm(" orr r1,r1,#1000h "); // reset the bit asm(" strh r1,[r0] "); //store the result asm(" ldr r0,addrCLKM "); // pick up CLKM clock register address asm(" ldrh r1,[r0] "); // take the current value of the register asm(" bic r1,r1,#1 "); // disable ARM clock asm(" strh r1,[r0] "); // ***************************************************** #if (CHIPSET == 15) asm(" .ref _exit_small_sleep"); asm(" BL _exit_small_sleep"); //Enable IRQs asm(" LDMFD sp!,{r1}"); //restore r2 from stack //asm(" MOV r1,r2"); // Move r2 to r1 asm(" MSR CPSR,r1 "); // Copy the contents of r1 to CPSR register #endif #if (W_A_CALYPSO_BUG_01435 == 1) asm(" MOV R0, #SMALL_SLEEP"); asm(" BL _f_arm_sleep_cmd"); #endif // ***************************************************** // CQ19599: For Calypso+ chipset, restore the extended // page mode if it was enabled before entering sleep // ***************************************************** #if (W_A_CALYPSO_PLUS_SPR_19599 == 1) asm(" .ref _f_memif_extended_page_mode_enable "); asm(" CMP r2,#0"); //check if extended page mode was enabled asm(" BEQ extended_page_mode_restored "); //if not, do nothing asm(" BL _f_memif_extended_page_mode_enable"); //else restore it asm("extended_page_mode_restored "); asm(" LDMFD sp!,{r2}"); //restore r2 #endif asm(" .ref TCT_Schedule_Loop "); asm("End_small_sleep "); asm(" B TCT_Schedule_Loop "); // Return to TCT_Schedule main loop asm("addrCLKM .word 0xfffffd00 ");//CLKM clock register address asm("Mode .word _mode_authorized "); asm("Switch .word _switch_PWR_MNGT "); #if (OP_L1_STANDALONE == 0) #if (TI_PROFILER == 1) asm(" .ref _ti_profiler_nb_sleep_call "); asm("profiler_counter .word _ti_profiler_nb_sleep_call "); #endif #endif // OP_L1_STANDALONE #endif /* __GNUC__ */