From ddeb215979b274729d2cfe4cb70fd438fb4524db Mon Sep 17 00:00:00 2001 From: "qing.han" Date: Tue, 2 Mar 2021 17:55:13 +0800 Subject: [PATCH 1/7] update phy adc funtion for calibrate --- components/driver/src/phy_adc.c | 128 ++++++++++++++++++++++---------- 1 file changed, 89 insertions(+), 39 deletions(-) diff --git a/components/driver/src/phy_adc.c b/components/driver/src/phy_adc.c index 42815d8..c411848 100755 --- a/components/driver/src/phy_adc.c +++ b/components/driver/src/phy_adc.c @@ -384,6 +384,7 @@ int phy_adc_config_channel(adc_Cfg_t cfg, adc_event_cb_t evt_handler) for (i = 2; i < 8; i++) { if (cfg.channel & BIT(i)) { gpio_pin_e pin = s_pinmap[i]; + phy_gpio_pull_set(pin,GPIO_FLOATING); phy_gpio_ds_control(pin, Bit_ENABLE); phy_gpio_cfg_analog_io(pin, Bit_ENABLE); @@ -468,6 +469,8 @@ int phy_adc_config_channel(adc_Cfg_t cfg, adc_event_cb_t evt_handler) set_differential_mode(); //LOG("%d %d %x\n",pin,pin_neg,*(volatile int*)0x40003800); + phy_gpio_pull_set(pin,GPIO_FLOATING); + phy_gpio_pull_set(pin_neg,GPIO_FLOATING); phy_gpio_cfg_analog_io(pin, Bit_ENABLE); phy_gpio_cfg_analog_io(pin_neg, Bit_ENABLE); //LOG("%d %d %x\n",pin,pin_neg,*(volatile int*)0x40003800); @@ -543,43 +546,83 @@ static void phy_adc_load_calibration_value(void) } } -int phy_adc_value_cal(adc_CH_t ch, uint16_t *buf, uint32_t size, bool high_resol, bool diff_mode) -{ - uint32_t i; - unsigned int adc_sum = 0; - float result = 0; - - for (i = 0; i < size; i++) { - adc_sum += (buf[i] & 0xfff); - } - phy_adc_load_calibration_value(); - result = (800 * adc_sum) / size;//800=0.8*1000 +//#if(SDK_VER_CHIP==__DEF_CHIP_QFN32__) +const unsigned short adc_Lambda[ADC_CH_NUM] = +{ + 0, //ADC_CH0 =0, + 0, //ADC_CH1 =1, + 869,//P11, + 810,//P23, + 823,//P24, + 840,//P14, + 798,//P15, + 767,//P20, + 0,//GPIO_DUMMY, //ADC_CH_VOICE =8, + +}; - //printf("->[%d %d]",buf[0],adc_sum); - if ((adc_cal_postive != 0xfff) && (adc_cal_negtive != 0xfff)) { - float delta = ((int)(adc_cal_postive - adc_cal_negtive)) / 2.0; +//#elif(SDK_VER_CHIP == __DEF_CHIP_TSOP16__) +/* +const unsigned short adc_Lambda[ADC_CH_NUM] = +{ + 0, //ADC_CH0 =0, + 0, //ADC_CH1 =1, + 867,//P11, + 0,//P23, + 0,//P24, + 857,//P14, + 800,//P15, + 780,//P20, + 0,//GPIO_DUMMY, //ADC_CH_VOICE =8, +}; +*/ +//#endif - if (ch & 0x01) { - result = (diff_mode) ? ((result - 2048 - delta) * 2 / (adc_cal_postive + adc_cal_negtive)) - : ((result + delta) / (adc_cal_postive + adc_cal_negtive)); - } else { - result = (diff_mode) ? ((result - 2048 - delta) * 2 / (adc_cal_postive + adc_cal_negtive)) - : ((result - delta) / (adc_cal_postive + adc_cal_negtive)); +int phy_adc_value_cal(adc_CH_t ch, uint16_t *buf, uint32_t size, bool high_resol, bool diff_mode) +{ + uint32_t i; + int adc_sum = 0; + volatile float result = 0.0; + + phy_adc_load_calibration_value(); + result = (float)buf[0]; + //printf("\n->%d %d %d %d\n",ch,adc_Lambda[ch],(int)result,size); + //printf("\n->%d\n",(int)result); + if((adc_cal_postive!=0xfff)&&(adc_cal_negtive!=0xfff)){ + float delta = ((int)(adc_cal_postive-adc_cal_negtive))/2.0; + if(ch&0x01) + { + result = (diff_mode) ? ((result-2048-delta)*2/(adc_cal_postive+adc_cal_negtive)) + : ((result+delta) /(adc_cal_postive+adc_cal_negtive)); } - - } else { - result = (diff_mode) ? (result / 2048 - 1) : (result / 4096); - } + else + { + result = (diff_mode) ? ((result-2048-delta)*2/(adc_cal_postive+adc_cal_negtive)) + : ((result-delta) /(adc_cal_postive+adc_cal_negtive)); + } + + }else{ - if (high_resol == FALSE) { - result = result * 4; - } - + result = (diff_mode) ? (float)(result / 2048 -1) : (float)(result /4096); + } + + if(high_resol == TRUE) + { + result *= 800; + } + else + { + result = (float)result *(float)adc_Lambda[ch]; + result = result*4096 /1000.0; + //printf("->%d\n",(int)(result)); + } return (int)result; } + + /* */ #include @@ -609,6 +652,8 @@ adc_handle_t drv_adc_initialize(int32_t idx, adc_event_cb_t cb_event) adc_priv->evt_handler = cb_event; + hal_clk_reset(MOD_ADCC); + hal_clk_gate_enable(MOD_ADCC); phy_adc_init(); @@ -687,8 +732,13 @@ int32_t drv_adc_config(adc_handle_t handle, adc_conf_t *config) adc_priv->mode = config->mode; adc_priv->intrp_mode = config->intrp_mode; - - adc_priv->cfg.is_continue_mode = TRUE; + if (config->mode == ADC_SINGLE) { + return ADC_PARAM_INVALID; + } else if (config->mode == ADC_CONTINUOUS) { + adc_priv->cfg.is_continue_mode = TRUE; + } else if (config->mode == ADC_SCAN) { + adc_priv->cfg.is_continue_mode = TRUE; + } adc_CLOCK_SEL_t clk; @@ -856,7 +906,7 @@ static uint32_t wait_data_ready(uint32_t sampling_frequency, int data_num, int c static int read_multiple_channel_n(adc_handle_t handle, uint32_t *data, uint32_t read_len) { ck_adc_priv_t *adc_priv = handle; - uint8_t channel_mask = adc_priv->channel;; + uint8_t channel_mask = adc_priv->channel; uint32_t adc_sum = 0; uint16_t adc_avg[1]; int ch = 2,ch_cur = 0,n = 0,i = 7; @@ -877,22 +927,22 @@ static int read_multiple_channel_n(adc_handle_t handle, uint32_t *data, uint32_t ch_cur=(ch%2)?(ch-1):(ch+1); - int temp = (++i)%8; - i = temp; + i=(++i)%8; adc_sum = 0; - for (n = 0; n < 16; n++) { + for (n = 0; n < 32; n++) { adc_sum += (uint16_t)(read_reg(ADC_CH_BASE + (ch_cur * 0x80) + ((n+2) * 4))&0xfff); adc_sum += (uint16_t)((read_reg(ADC_CH_BASE + (ch_cur * 0x80) + ((n+2) * 4))>>16)&0xfff); } //data[i] = (uint16_t)(adc_sum>>5); - adc_avg[0] = (uint16_t)(adc_sum>>5); - high_resol = (adc_priv->cfg.is_high_resolution & (1ul<cfg.is_differential_mode & (1ul<>6); + high_resol = (s_adc_cfg.is_high_resolution & (1ul<mode == ADC_SINGLE) { - read_multiple_channel_n(handle, data, num); + //read_data_one_channel_n(handle, data, num); } else if (adc_priv->mode == ADC_CONTINUOUS) { read_multiple_channel_n(handle, data, num); } else if (adc_priv->mode == ADC_SCAN) { -- Gitee From 01ddd1bdf7103b56d66199b92b816d3d3bb63021 Mon Sep 17 00:00:00 2001 From: "qing.han" Date: Fri, 5 Nov 2021 11:31:44 +0800 Subject: [PATCH 2/7] 1.Bugfix csi driver 2.uodate adc driver 3.Bugfix xtal short circuit case --- components/controller/rf_phy_driver.h | 2 +- components/driver/src/gpio.c | 14 + components/driver/src/phy_adc.c | 93 ++----- components/inc/mcu.h | 6 +- components/osal/include/OSAL.h | 282 ------------------- components/osal/include/OSAL_Clock.h | 110 -------- components/osal/include/OSAL_Memory.h | 124 --------- components/osal/include/OSAL_Nv.h | 111 -------- components/osal/include/OSAL_PwrMgr.h | 111 -------- components/osal/include/OSAL_Tasks.h | 65 ----- components/osal/include/OSAL_Timers.h | 118 -------- components/osal/include/osal_bufmgr.h | 80 ------ components/osal/include/osal_cbtimer.h | 102 ------- components/osal/include/osal_snv.h | 139 ---------- csi_drivers/dw_usart.c | 37 +-- csi_drivers/dw_wdt.c | 9 +- csi_drivers/spif.c | 206 ++++++++++++-- flash/PHY6220_Flash.elf | Bin 79664 -> 81844 bytes include/dw_dmac.h | 1 + include/spif.h | 44 +++ misc/rom_sym_def.h | 12 +- phy_pmu.c | 38 ++- pm.c | 360 +++++++++++++++++++++++-- reboot.c | 46 +++- system.c | 29 +- 25 files changed, 749 insertions(+), 1390 deletions(-) delete mode 100755 components/osal/include/OSAL.h delete mode 100755 components/osal/include/OSAL_Clock.h delete mode 100755 components/osal/include/OSAL_Memory.h delete mode 100755 components/osal/include/OSAL_Nv.h delete mode 100755 components/osal/include/OSAL_PwrMgr.h delete mode 100755 components/osal/include/OSAL_Tasks.h delete mode 100755 components/osal/include/OSAL_Timers.h delete mode 100755 components/osal/include/osal_bufmgr.h delete mode 100755 components/osal/include/osal_cbtimer.h delete mode 100755 components/osal/include/osal_snv.h diff --git a/components/controller/rf_phy_driver.h b/components/controller/rf_phy_driver.h index 52c172b..eecaa5c 100755 --- a/components/controller/rf_phy_driver.h +++ b/components/controller/rf_phy_driver.h @@ -120,7 +120,7 @@ extern volatile uint32_t g_dtmAccessCode ; /******************************************************************************* * MACRO */ - +#define RF_PHY_EXT_PREAMBLE_US (8) // ext ble preamble length #define PHY_REG_RD(x) *(volatile uint32_t *)(x) #define PHY_REG_WT(x,y) *(volatile uint32_t *)(x) = (y) diff --git a/components/driver/src/gpio.c b/components/driver/src/gpio.c index d170f4c..99e0f11 100755 --- a/components/driver/src/gpio.c +++ b/components/driver/src/gpio.c @@ -553,6 +553,20 @@ __attribute__((section(".__sram.code"))) void phy_gpioretention_prepare_sleep_ac } } +__attribute__((section(".__sram.code"))) void phy_gpioretention_disable(void) +{ + gpio_pin_e pin=0; + + for(pin=0;pinPMCTL0 &= ~BIT(retention_reg[pin][1]); + } else { + AP_AON->IOCTL[retention_reg[pin][0]] &= ~BIT(retention_reg[pin][1]); + } + } +} + __attribute__((section(".__sram.code"))) void phy_gpioretention_prepare_wakeup_action(void) { gpio_pin_e pin=0; diff --git a/components/driver/src/phy_adc.c b/components/driver/src/phy_adc.c index c411848..bf5c080 100755 --- a/components/driver/src/phy_adc.c +++ b/components/driver/src/phy_adc.c @@ -1,46 +1,4 @@ -/************************************************************************************************** - - Phyplus Microelectronics Limited confidential and proprietary. - All rights reserved. - - IMPORTANT: All rights of this software belong to Phyplus Microelectronics - Limited ("Phyplus"). Your use of this Software is limited to those - specific rights granted under the terms of the business contract, the - confidential agreement, the non-disclosure agreement and any other forms - of agreements as a customer or a partner of Phyplus. You may not use this - Software unless you agree to abide by the terms of these agreements. - You acknowledge that the Software may not be modified, copied, - distributed or disclosed unless embedded on a Phyplus Bluetooth Low Energy - (BLE) integrated circuit, either as a product or is integrated into your - products. Other than for the aforementioned purposes, you may not use, - reproduce, copy, prepare derivative works of, modify, distribute, perform, - display or sell this Software and/or its documentation for any purposes. - - YOU FURTHER ACKNOWLEDGE AND AGREE THAT THE SOFTWARE AND DOCUMENTATION ARE - PROVIDED AS IS WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED, - INCLUDING WITHOUT LIMITATION, ANY WARRANTY OF MERCHANTABILITY, TITLE, - NON-INFRINGEMENT AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL - PHYPLUS OR ITS SUBSIDIARIES BE LIABLE OR OBLIGATED UNDER CONTRACT, - NEGLIGENCE, STRICT LIABILITY, CONTRIBUTION, BREACH OF WARRANTY, OR OTHER - LEGAL EQUITABLE THEORY ANY DIRECT OR INDIRECT DAMAGES OR EXPENSES - INCLUDING BUT NOT LIMITED TO ANY INCIDENTAL, SPECIAL, INDIRECT, PUNITIVE - OR CONSEQUENTIAL DAMAGES, LOST PROFITS OR LOST DATA, COST OF PROCUREMENT - OF SUBSTITUTE GOODS, TECHNOLOGY, SERVICES, OR ANY CLAIMS BY THIRD PARTIES - (INCLUDING BUT NOT LIMITED TO ANY DEFENSE THEREOF), OR OTHER SIMILAR COSTS. - -**************************************************************************************************/ - -/******************************************************************************* -* @file adc.c -* @brief Contains all functions support for adc driver -* @version 0.0 -* @date 18. Oct. 2017 -* @author qing.han -* -* Copyright(C) 2016, PhyPlus Semiconductor -* All rights reserved. -* -*******************************************************************************/ + #include #include "error.h" #include "gpio.h" @@ -537,27 +495,32 @@ int phy_adc_stop(void) **************************************************************************************/ static void phy_adc_load_calibration_value(void) { - if (adc_cal_read_flag == FALSE) { - adc_cal_read_flag = TRUE; - adc_cal_negtive = read_reg(0x11001000) & 0x0fff; - adc_cal_postive = (read_reg(0x11001000) >> 16) & 0x0fff; - //printf("->adc_cal_negtive:%x\n",adc_cal_negtive); - //printf("->adc_cal_postive:%x\n",adc_cal_postive); - } + if (adc_cal_read_flag == FALSE) { + adc_cal_read_flag = TRUE; + adc_cal_negtive = read_reg(0x11001000) & 0x0fff; + adc_cal_postive = (read_reg(0x11001000) >> 16) & 0x0fff; + + if((adc_cal_negtive < 0x733)||(adc_cal_negtive > 0x8cc) ||(adc_cal_postive < 0x733)||(adc_cal_postive > 0x8cc)){ + adc_cal_negtive = 0xfff; + adc_cal_postive = 0xfff; + } + } } //#if(SDK_VER_CHIP==__DEF_CHIP_QFN32__) -const unsigned short adc_Lambda[ADC_CH_NUM] = +const unsigned int adc_Lambda[ADC_CH_NUM] = { 0, //ADC_CH0 =0, 0, //ADC_CH1 =1, - 869,//P11, - 810,//P23, - 823,//P24, - 840,//P14, - 798,//P15, - 767,//P20, + + 4591524,//P11, + 4307418,//P23, + 4322922,//P24, + 4514182,//P14, + 4182689,//P15, + 4047198,//P20, + 0,//GPIO_DUMMY, //ADC_CH_VOICE =8, }; @@ -588,18 +551,18 @@ int phy_adc_value_cal(adc_CH_t ch, uint16_t *buf, uint32_t size, bool high_resol phy_adc_load_calibration_value(); result = (float)buf[0]; //printf("\n->%d %d %d %d\n",ch,adc_Lambda[ch],(int)result,size); - //printf("\n->%d\n",(int)result); + //printf("[%d]",(int)result); if((adc_cal_postive!=0xfff)&&(adc_cal_negtive!=0xfff)){ float delta = ((int)(adc_cal_postive-adc_cal_negtive))/2.0; if(ch&0x01) { result = (diff_mode) ? ((result-2048-delta)*2/(adc_cal_postive+adc_cal_negtive)) - : ((result+delta) /(adc_cal_postive+adc_cal_negtive)); + : ((result-delta) /(adc_cal_postive+adc_cal_negtive)); } else { result = (diff_mode) ? ((result-2048-delta)*2/(adc_cal_postive+adc_cal_negtive)) - : ((result-delta) /(adc_cal_postive+adc_cal_negtive)); + : ((result+delta) /(adc_cal_postive+adc_cal_negtive)); } }else{ @@ -613,9 +576,7 @@ int phy_adc_value_cal(adc_CH_t ch, uint16_t *buf, uint32_t size, bool high_resol } else { - result = (float)result *(float)adc_Lambda[ch]; - result = result*4096 /1000.0; - //printf("->%d\n",(int)(result)); + result = (float)result *(float)adc_Lambda[ch]*0.8*0.001; } return (int)result; } @@ -672,7 +633,7 @@ int32_t drv_adc_uninitialize(adc_handle_t handle) //hal_pwrmgr_register(MOD_ADCC,NULL,NULL); phy_clear_adcc_cfg(); //hal_adc_init(); - + AP_AON->PMCTL2_1 =0x00; hal_clk_gate_disable(MOD_ADCC); return 0; @@ -929,14 +890,14 @@ static int read_multiple_channel_n(adc_handle_t handle, uint32_t *data, uint32_t i=(++i)%8; adc_sum = 0; - for (n = 0; n < 32; n++) { + for (n = 0; n < 29; n++) { adc_sum += (uint16_t)(read_reg(ADC_CH_BASE + (ch_cur * 0x80) + ((n+2) * 4))&0xfff); adc_sum += (uint16_t)((read_reg(ADC_CH_BASE + (ch_cur * 0x80) + ((n+2) * 4))>>16)&0xfff); } //data[i] = (uint16_t)(adc_sum>>5); - adc_avg[0] = (uint16_t)(adc_sum>>6); + adc_avg[0] = (uint16_t)(adc_sum/58); high_resol = (s_adc_cfg.is_high_resolution & (1ul<=y) ? x-y : TIME_BASE-y+x ) diff --git a/components/osal/include/OSAL.h b/components/osal/include/OSAL.h deleted file mode 100755 index 8843110..0000000 --- a/components/osal/include/OSAL.h +++ /dev/null @@ -1,282 +0,0 @@ -/****************************************************************************** - Filename: OSAL.h - Revised: - Revision: - - Description: This API allows the software components in the Z-Stack to be - written independently of the specifics of the operating system, - kernel, or tasking environment (including control loops or - connect-to-interrupt systems). - - - -******************************************************************************/ - -#ifndef OSAL_H -#define OSAL_H - -#ifdef __cplusplus -extern "C" -{ -#endif - -/********************************************************************* - * INCLUDES - */ - -//#include - -#ifndef UINT_MAX -#define UINT_MAX (~0U) -#endif - -#include "comdef.h" -#include "OSAL_Memory.h" -#include "OSAL_Timers.h" - -/********************************************************************* - * MACROS - */ -#if ( UINT_MAX == 65535 ) /* 8-bit and 16-bit devices */ -#define osal_offsetof(type, member) ((uint16) &(((type *) 0)->member)) -#else /* 32-bit devices */ -#define osal_offsetof(type, member) ((uint32) &(((type *) 0)->member)) -#endif - -#define OSAL_MSG_NEXT(msg_ptr) ((osal_msg_hdr_t *) (msg_ptr) - 1)->next - -#define OSAL_MSG_Q_INIT(q_ptr) *(q_ptr) = NULL - -#define OSAL_MSG_Q_EMPTY(q_ptr) (*(q_ptr) == NULL) - -#define OSAL_MSG_Q_HEAD(q_ptr) (*(q_ptr)) - -#define OSAL_MSG_LEN(msg_ptr) ((osal_msg_hdr_t *) (msg_ptr) - 1)->len - -#define OSAL_MSG_ID(msg_ptr) ((osal_msg_hdr_t *) (msg_ptr) - 1)->dest_id - -/********************************************************************* - * CONSTANTS - */ - -/*** Interrupts ***/ -#define INTS_ALL 0xFF - -/********************************************************************* - * TYPEDEFS - */ -typedef struct { - void *next; - uint16 len; - uint8 dest_id; -} osal_msg_hdr_t; - -typedef struct { - uint8 event; - uint8 status; -} osal_event_hdr_t; - -typedef void *osal_msg_q_t; - -/********************************************************************* - * GLOBAL VARIABLES - */ - -/********************************************************************* - * FUNCTIONS - */ - -/*** Message Management ***/ - -/* - * Task Message Allocation - */ -extern uint8 *osal_msg_allocate(uint16 len); - -/* - * Task Message Deallocation - */ -extern uint8 osal_msg_deallocate(uint8 *msg_ptr); - -/* - * Send a Task Message - */ -extern uint8 osal_msg_send(uint8 destination_task, uint8 *msg_ptr); - -/* - * Push a Task Message to head of queue - */ -extern uint8 osal_msg_push_front(uint8 destination_task, uint8 *msg_ptr); - -/* - * Receive a Task Message - */ -extern uint8 *osal_msg_receive(uint8 task_id); - -/* - * Find in place a matching Task Message / Event. - */ -extern osal_event_hdr_t *osal_msg_find(uint8 task_id, uint8 event); - -/* - * Enqueue a Task Message - */ -extern void osal_msg_enqueue(osal_msg_q_t *q_ptr, void *msg_ptr); - -/* - * Enqueue a Task Message Up to Max - */ -extern uint8 osal_msg_enqueue_max(osal_msg_q_t *q_ptr, void *msg_ptr, uint8 max); - -/* - * Dequeue a Task Message - */ -extern void *osal_msg_dequeue(osal_msg_q_t *q_ptr); - -/* - * Push a Task Message to head of queue - */ -extern void osal_msg_push(osal_msg_q_t *q_ptr, void *msg_ptr); - -/* - * Extract and remove a Task Message from queue - */ -extern void osal_msg_extract(osal_msg_q_t *q_ptr, void *msg_ptr, void *prev_ptr); - - -/*** Task Synchronization ***/ - -/* - * Set a Task Event - */ -extern uint8 osal_set_event(uint8 task_id, uint16 event_flag); - - -/* - * Clear a Task Event - */ -extern uint8 osal_clear_event(uint8 task_id, uint16 event_flag); - - -/*** Interrupt Management ***/ - -/* - * Register Interrupt Service Routine (ISR) - */ -extern uint8 osal_isr_register(uint8 interrupt_id, void (*isr_ptr)(uint8 *)); - -/* - * Enable Interrupt - */ -extern uint8 osal_int_enable(uint8 interrupt_id); - -/* - * Disable Interrupt - */ -extern uint8 osal_int_disable(uint8 interrupt_id); - - -/*** Task Management ***/ - -/* - * Initialize the Task System - */ -extern uint8 osal_init_system(void); - -/* - * System Processing Loop - */ -#if defined (ZBIT) -extern __declspec(dllexport) void osal_start_system(void); -#else -extern void osal_start_system(void); -#endif - -/* - * One Pass Throu the OSAL Processing Loop - */ -extern void osal_run_system(void); - -/* - * Get the active task ID - */ -extern uint8 osal_self(void); - - -/*** Helper Functions ***/ - -/* - * String Length - */ -extern int osal_strlen(char *pString); - -/* - * Memory copy - */ -extern void *osal_memcpy(void *, const void GENERIC *, unsigned int); - -/* - * Memory Duplicate - allocates and copies - */ -extern void *osal_memdup(const void GENERIC *src, unsigned int len); - -/* - * Reverse Memory copy - */ -extern void *osal_revmemcpy(void *, const void GENERIC *, unsigned int); - -/* - * Memory compare - */ -extern uint8 osal_memcmp(const void GENERIC *src1, const void GENERIC *src2, unsigned int len); - -/* - * Memory set - */ -extern void *osal_memset(void *dest, uint8 value, int len); - -/* - * Build a uint16 out of 2 bytes (0 then 1). - */ -extern uint16 osal_build_uint16(uint8 *swapped); - -/* - * Build a uint32 out of sequential bytes. - */ -extern uint32 osal_build_uint32(uint8 *swapped, uint8 len); - -/* - * Convert long to ascii string - */ -#if !defined ( ZBIT ) && !defined ( ZBIT2 ) && !defined (UBIT) -extern uint8 *_ltoa(uint32 l, uint8 *buf, uint8 radix); -#endif - -/* - * Random number generator - */ -extern uint16 osal_rand(void); - -/* - * Buffer an uint32 value - LSB first. - */ -extern uint8 *osal_buffer_uint32(uint8 *buf, uint32 val); - -/* - * Buffer an uint24 value - LSB first - */ -extern uint8 *osal_buffer_uint24(uint8 *buf, uint24 val); - -/* - * Is all of the array elements set to a value? - */ -extern uint8 osal_isbufset(uint8 *buf, uint8 val, uint8 len); - -/********************************************************************* -*********************************************************************/ - -#ifdef __cplusplus -} -#endif - -#endif /* OSAL_H */ diff --git a/components/osal/include/OSAL_Clock.h b/components/osal/include/OSAL_Clock.h deleted file mode 100755 index fdcd66e..0000000 --- a/components/osal/include/OSAL_Clock.h +++ /dev/null @@ -1,110 +0,0 @@ -/****************************************************************************** - Filename: OSAL_Clock.h - Revised: - Revision: - - Description: OSAL Clock definition and manipulation functions. - - - -******************************************************************************/ - -#ifndef OSAL_CLOCK_H -#define OSAL_CLOCK_H - -#ifdef __cplusplus -extern "C" -{ -#endif - -/********************************************************************* - * INCLUDES - */ - -/********************************************************************* - * MACROS - */ - -#define IsLeapYear(yr) (!((yr) % 400) || (((yr) % 100) && !((yr) % 4))) - -/********************************************************************* - * CONSTANTS - */ - -/********************************************************************* - * TYPEDEFS - */ - -// number of seconds since 0 hrs, 0 minutes, 0 seconds, on the -// 1st of January 2000 UTC -typedef unsigned int UTCTime; // to confirm , int is 32bits long - -// To be used with -typedef struct { - uint8 seconds; // 0-59 - uint8 minutes; // 0-59 - uint8 hour; // 0-23 - uint8 day; // 0-30 - uint8 month; // 0-11 - uint16 year; // 2000+ -} UTCTimeStruct; - -/********************************************************************* - * GLOBAL VARIABLES - */ - -/********************************************************************* - * FUNCTIONS - */ - -/* - * Updates the OSAL clock and Timers from the MAC 320us timer tick. - */ -extern void osalTimeUpdate(void); - -/* - * Set the new time. This will only set the seconds portion - * of time and doesn't change the factional second counter. - * newTime - number of seconds since 0 hrs, 0 minutes, - * 0 seconds, on the 1st of January 2000 UTC - */ -extern void osal_setClock(UTCTime newTime); - -/* - * Gets the current time. This will only return the seconds - * portion of time and doesn't include the factional second counter. - * returns: number of seconds since 0 hrs, 0 minutes, - * 0 seconds, on the 1st of January 2000 UTC - */ -extern UTCTime osal_getClock(void); - -/* - * Converts UTCTime to UTCTimeStruct - * - * secTime - number of seconds since 0 hrs, 0 minutes, - * 0 seconds, on the 1st of January 2000 UTC - * tm - pointer to breakdown struct - */ -extern void osal_ConvertUTCTime(UTCTimeStruct *tm, UTCTime secTime); - -/* - * Converts UTCTimeStruct to UTCTime (seconds since 00:00:00 01/01/2000) - * - * tm - pointer to UTC time struct - */ -extern UTCTime osal_ConvertUTCSecs(UTCTimeStruct *tm); - -/* - * Update/Adjust the osal clock and timers - * Msec - elapsed time in milli seconds - */ -extern void osalAdjustTimer(uint32 Msec); - -/********************************************************************* -*********************************************************************/ - -#ifdef __cplusplus -} -#endif - -#endif /* OSAL_CLOCK_H */ diff --git a/components/osal/include/OSAL_Memory.h b/components/osal/include/OSAL_Memory.h deleted file mode 100755 index de9215c..0000000 --- a/components/osal/include/OSAL_Memory.h +++ /dev/null @@ -1,124 +0,0 @@ -/************************************************************************************************** - Filename: OSAL_Memory.h - Revised: - Revision: - - Description: This module defines the OSAL memory control functions. - - - -**************************************************************************************************/ - -#ifndef OSAL_MEMORY_H -#define OSAL_MEMORY_H - -#ifdef __cplusplus -extern "C" -{ -#endif - -/********************************************************************* - * INCLUDES - */ -#include "comdef.h" - -/********************************************************************* - * CONSTANTS - */ - -#if !defined ( OSALMEM_METRICS ) -#define OSALMEM_METRICS FALSE -#endif - -/********************************************************************* - * MACROS - */ - -//#define osal_stack_used() OnBoard_stack_used() - -/********************************************************************* - * TYPEDEFS - */ - -typedef struct { - // The 15 LSB's of 'val' indicate the total item size, including the header, in 8-bit bytes. - unsigned short len : 15; // unsigned short len : 15; - // The 1 MSB of 'val' is used as a boolean to indicate in-use or freed. - unsigned short inUse : 1; // unsigned short inUse : 1; -} osalMemHdrHdr_t; - -typedef union { - /* Dummy variable so compiler forces structure to alignment of largest element while not wasting - * space on targets when the halDataAlign_t is smaller than a UINT16. - */ - halDataAlign_t alignDummy; - uint32 val; // uint16 // TODO: maybe due to 4 byte alignment requirement in M0, this union should be 4 byte, change from uint16 to uint32, investigate more later - 04-25 - osalMemHdrHdr_t hdr; -} osalMemHdr_t; - -/********************************************************************* - * GLOBAL VARIABLES - */ - -/********************************************************************* - * FUNCTIONS - */ - -/* - * Initialize memory manager. - */ -void osal_mem_init(void); - -/* - * Setup efficient search for the first free block of heap. - */ -void osal_mem_kick(void); - -/* - * Allocate a block of memory. - */ -void *osal_mem_alloc(uint16 size); - -/* - * Free a block of memory. - */ -void osal_mem_free(void *ptr); - - -// ====== A2 metal change add -/* - * Set osal memory buffer - */ -void osal_mem_set_heap(osalMemHdr_t *hdr, uint32 size); - -#if ( OSALMEM_METRICS ) -/* - * Return the maximum number of blocks ever allocated at once. - */ -uint16 osal_heap_block_max(void); - -/* - * Return the current number of blocks now allocated. - */ -uint16 osal_heap_block_cnt(void); - -/* - * Return the current number of free blocks. - */ -uint16 osal_heap_block_free(void); - -/* - * Return the current number of bytes allocated. - */ -uint16 osal_heap_mem_used(void); -#endif - - -/********************************************************************* -*********************************************************************/ - -#ifdef __cplusplus -} -#endif - -#endif /* #ifndef OSAL_MEMORY_H */ diff --git a/components/osal/include/OSAL_Nv.h b/components/osal/include/OSAL_Nv.h deleted file mode 100755 index 4eb0906..0000000 --- a/components/osal/include/OSAL_Nv.h +++ /dev/null @@ -1,111 +0,0 @@ -/************************************************************************************************** - Filename: OSAL_Nv.h - Revised: $Date: 2011-05-31 09:28:05 -0700 (Tue, 31 May 2011) $ - Revision: $Revision: 26152 $ - - Description: This module defines the OSAL non-volatile memory functions. - - - Copyright 2004-2011 Texas Instruments Incorporated. All rights reserved. - - IMPORTANT: Your use of this Software is limited to those specific rights - granted under the terms of a software license agreement between the user - who downloaded the software, his/her employer (which must be your employer) - and Texas Instruments Incorporated (the "License"). You may not use this - Software unless you agree to abide by the terms of the License. The License - limits your use, and you acknowledge, that the Software may not be modified, - copied or distributed unless embedded on a Texas Instruments microcontroller - or used solely and exclusively in conjunction with a Texas Instruments radio - frequency transceiver, which is integrated into your product. Other than for - the foregoing purpose, you may not use, reproduce, copy, prepare derivative - works of, modify, distribute, perform, display or sell this Software and/or - its documentation for any purpose. - - YOU FURTHER ACKNOWLEDGE AND AGREE THAT THE SOFTWARE AND DOCUMENTATION ARE - PROVIDED “AS IS” WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED, - INCLUDING WITHOUT LIMITATION, ANY WARRANTY OF MERCHANTABILITY, TITLE, - NON-INFRINGEMENT AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL - TEXAS INSTRUMENTS OR ITS LICENSORS BE LIABLE OR OBLIGATED UNDER CONTRACT, - NEGLIGENCE, STRICT LIABILITY, CONTRIBUTION, BREACH OF WARRANTY, OR OTHER - LEGAL EQUITABLE THEORY ANY DIRECT OR INDIRECT DAMAGES OR EXPENSES - INCLUDING BUT NOT LIMITED TO ANY INCIDENTAL, SPECIAL, INDIRECT, PUNITIVE - OR CONSEQUENTIAL DAMAGES, LOST PROFITS OR LOST DATA, COST OF PROCUREMENT - OF SUBSTITUTE GOODS, TECHNOLOGY, SERVICES, OR ANY CLAIMS BY THIRD PARTIES - (INCLUDING BUT NOT LIMITED TO ANY DEFENSE THEREOF), OR OTHER SIMILAR COSTS. - - Should you have any questions regarding your right to use this Software, - contact Texas Instruments Incorporated at www.TI.com. -**************************************************************************************************/ - -#ifndef OSAL_NV_H -#define OSAL_NV_H - -#ifdef __cplusplus -extern "C" -{ -#endif - -/********************************************************************* - * INCLUDES - */ - -#include "hal_types.h" - -/********************************************************************* - * CONSTANTS - */ - -/********************************************************************* - * MACROS - */ - -/********************************************************************* - * TYPEDEFS - */ - -/********************************************************************* - * GLOBAL VARIABLES - */ - -/********************************************************************* - * FUNCTIONS - */ - -/* - * Initialize NV service - */ -extern void osal_nv_init(void *p); - -/* - * Initialize an item in NV - */ -extern uint8 osal_nv_item_init(uint16 id, uint16 len, void *buf); - -/* - * Read an NV attribute - */ -extern uint8 osal_nv_read(uint16 id, uint16 offset, uint16 len, void *buf); - -/* - * Write an NV attribute - */ -extern uint8 osal_nv_write(uint16 id, uint16 offset, uint16 len, void *buf); - -/* - * Get the length of an NV item. - */ -extern uint16 osal_nv_item_len(uint16 id); - -/* - * Delete an NV item. - */ -extern uint8 osal_nv_delete(uint16 id, uint16 len); - -/********************************************************************* -*********************************************************************/ - -#ifdef __cplusplus -} -#endif - -#endif /* OSAL_NV.H */ diff --git a/components/osal/include/OSAL_PwrMgr.h b/components/osal/include/OSAL_PwrMgr.h deleted file mode 100755 index d03dc93..0000000 --- a/components/osal/include/OSAL_PwrMgr.h +++ /dev/null @@ -1,111 +0,0 @@ -/************************************************************************************************** - Filename: OSAL_PwrMgr.h - Revised: - Revision: - - Description: This file contains the OSAL Power Management API. - - - **************************************************************************************************/ - -#ifndef OSAL_PWRMGR_H -#define OSAL_PWRMGR_H - -#include "comdef.h" - -#ifdef __cplusplus -extern "C" -{ -#endif - -/********************************************************************* - * INCLUDES - */ - -/********************************************************************* - * MACROS - */ - -/********************************************************************* - * TYPEDEFS - */ - -/* These attributes define sleep beheaver. The attributes can be changed - * for each sleep cycle or when the device characteristic change. - */ -typedef struct { - uint16 pwrmgr_task_state; - uint16 pwrmgr_next_timeout; - uint16 accumulated_sleep_time; - uint8 pwrmgr_device; -} pwrmgr_attribute_t; - -/* With PWRMGR_ALWAYS_ON selection, there is no power savings and the - * device is most likely on mains power. The PWRMGR_BATTERY selection allows - * the HAL sleep manager to enter SLEEP LITE state or SLEEP DEEP state. - */ -#define PWRMGR_ALWAYS_ON 0 -#define PWRMGR_BATTERY 1 - -/* The PWRMGR_CONSERVE selection turns power savings on, all tasks have to - * agree. The PWRMGR_HOLD selection turns power savings off. - */ -#define PWRMGR_CONSERVE 0 -#define PWRMGR_HOLD 1 - - -/********************************************************************* - * GLOBAL VARIABLES - */ - -/* This global variable stores the power management attributes. - */ -extern pwrmgr_attribute_t pwrmgr_attribute; - -/********************************************************************* - * FUNCTIONS - */ - -/* - * Initialize the power management system. - * This function is called from OSAL. - * - */ -extern void osal_pwrmgr_init(void); - -/* - * This function is called by each task to state whether or not this - * task wants to conserve power. The task will call this function to - * vote whether it wants the OSAL to conserve power or it wants to - * hold off on the power savings. By default, when a task is created, - * its own power state is set to conserve. If the task always wants - * to converse power, it doesn't need to call this function at all. - * It is important for the task that changed the power manager task - * state to PWRMGR_HOLD to switch back to PWRMGR_CONSERVE when the - * hold period ends. - */ -extern uint8 osal_pwrmgr_task_state(uint8 task_id, uint8 state); - -/* - * This function is called on power-up, whenever the device characteristic - * change (ex. Battery backed coordinator). This function works with the timer - * to set HAL's power manager sleep state when power saving is entered. - * This function should be called form HAL initialization. After power up - * initialization, it should only be called from NWK or ZDO. - */ -extern void osal_pwrmgr_device(uint8 pwrmgr_device); - -/* - * This function is called from the main OSAL loop when there are - * no events scheduled and shouldn't be called from anywhere else. - */ -extern void osal_pwrmgr_powerconserve(void); - -/********************************************************************* -*********************************************************************/ - -#ifdef __cplusplus -} -#endif - -#endif /* OSAL_PWRMGR_H */ diff --git a/components/osal/include/OSAL_Tasks.h b/components/osal/include/OSAL_Tasks.h deleted file mode 100755 index f0b5cea..0000000 --- a/components/osal/include/OSAL_Tasks.h +++ /dev/null @@ -1,65 +0,0 @@ -/************************************************************************************************** - Filename: OSAL_Tasks.h - Revised: - Revision: - - Description: This file contains the OSAL Task definition and manipulation functions. - - -**************************************************************************************************/ - -#ifndef OSAL_TASKS_H -#define OSAL_TASKS_H - -#ifdef __cplusplus -extern "C" -{ -#endif - -/********************************************************************* - * INCLUDES - */ - -/********************************************************************* - * MACROS - */ - -/********************************************************************* - * CONSTANTS - */ -#define TASK_NO_TASK 0xFF - -/********************************************************************* - * TYPEDEFS - */ - -/* - * Event handler function prototype - */ -typedef unsigned short(*pTaskEventHandlerFn)(unsigned char task_id, unsigned short event); - -/********************************************************************* - * GLOBAL VARIABLES - */ - -extern pTaskEventHandlerFn tasksArr[]; -extern uint8 tasksCnt; -extern uint16 *tasksEvents; - -/********************************************************************* - * FUNCTIONS - */ - -/* - * Call each of the tasks initailization functions. - */ -extern void osalInitTasks(void); - -/********************************************************************* -*********************************************************************/ - -#ifdef __cplusplus -} -#endif - -#endif /* OSAL_TASKS_H */ diff --git a/components/osal/include/OSAL_Timers.h b/components/osal/include/OSAL_Timers.h deleted file mode 100755 index 7b17f9b..0000000 --- a/components/osal/include/OSAL_Timers.h +++ /dev/null @@ -1,118 +0,0 @@ -/************************************************************************************************** - Filename: OSAL_Timers.h - Revised: - Revision: - - Description: This file contains the OSAL Timer definition and manipulation functions. - - - -**************************************************************************************************/ - -#ifndef OSAL_TIMERS_H -#define OSAL_TIMERS_H - -#ifdef __cplusplus -extern "C" -{ -#endif - -/********************************************************************* - * INCLUDES - */ - -/********************************************************************* - * MACROS - */ - -/********************************************************************* - * CONSTANTS - * the unit is chosen such that the 320us tick equivalent can fit in - * 32 bits. - */ -#define OSAL_TIMERS_MAX_TIMEOUT 0x28f5c28e /* unit is ms*/ - -/********************************************************************* - * TYPEDEFS - */ - -/********************************************************************* - * GLOBAL VARIABLES - */ - -/********************************************************************* - * FUNCTIONS - */ - -/* - * Initialization for the OSAL Timer System. - */ -extern void osalTimerInit(void); - -/* - * Set a Timer - */ -extern uint8 osal_start_timerEx(uint8 task_id, uint16 event_id, uint32 timeout_value); - -/* - * Set a timer that reloads itself. - */ -extern uint8 osal_start_reload_timer(uint8 taskID, uint16 event_id, uint32 timeout_value); - -/* - * Stop a Timer - */ -extern uint8 osal_stop_timerEx(uint8 task_id, uint16 event_id); - -/* - * Get the tick count of a Timer. - */ -extern uint32 osal_get_timeoutEx(uint8 task_id, uint16 event_id); - -/* - * Simulated Timer Interrupt Service Routine - */ - -extern void osal_timer_ISR(void); - -/* - * Adjust timer tables - */ -extern void osal_adjust_timers(void); - -/* - * Update timer tables - */ -extern void osalTimerUpdate(uint32 updateTime); - -/* - * Count active timers - */ -extern uint8 osal_timer_num_active(void); - -/* - * Set the hardware timer interrupts for sleep mode. - * These functions should only be called in OSAL_PwrMgr.c - */ -extern void osal_sleep_timers(void); -extern void osal_unsleep_timers(void); - -/* - * Read the system clock - returns milliseconds - */ -extern uint32 osal_GetSystemClock(void); - -/* - * Get the next OSAL timer expiration. - * This function should only be called in OSAL_PwrMgr.c - */ -extern uint32 osal_next_timeout(void); - -/********************************************************************* -*********************************************************************/ - -#ifdef __cplusplus -} -#endif - -#endif /* OSAL_TIMERS_H */ diff --git a/components/osal/include/osal_bufmgr.h b/components/osal/include/osal_bufmgr.h deleted file mode 100755 index 6d5fb8f..0000000 --- a/components/osal/include/osal_bufmgr.h +++ /dev/null @@ -1,80 +0,0 @@ -/************************************************************************************************** - Filename: osal_bufmgr.h - Revised: - Revision: - - Description: This file contains the buffer management definitions. - - - -**************************************************************************************************/ - -#ifndef OSAL_BUFMGR_H -#define OSAL_BUFMGR_H - -#include "comdef.h" -#ifdef __cplusplus -extern "C" -{ -#endif - -/********************************************************************* - * INCLUDES - */ - -/********************************************************************* - * CONSTANTS - */ - - -/********************************************************************* - * VARIABLES - */ - - -/********************************************************************* - * MACROS - */ - - -/********************************************************************* - * TYPEDEFS - */ - - -/********************************************************************* - * VARIABLES - */ - -/********************************************************************* - * FUNCTIONS - */ - -/* - * Allocate a block of memory. - */ -extern void *osal_bm_alloc(uint16 size); - -/* - * Add or remove header space for the payload pointer. - */ -extern void *osal_bm_adjust_header(void *payload_ptr, int16 size); - -/* - * Add or remove tail space for the payload pointer. - */ -extern void *osal_bm_adjust_tail(void *payload_ptr, int16 size); - -/* - * Free a block of memory. - */ -extern void osal_bm_free(void *payload_ptr); - -/********************************************************************* -*********************************************************************/ - -#ifdef __cplusplus -} -#endif - -#endif /* OSAL_BUFMGR_H */ diff --git a/components/osal/include/osal_cbtimer.h b/components/osal/include/osal_cbtimer.h deleted file mode 100755 index 97c2dc8..0000000 --- a/components/osal/include/osal_cbtimer.h +++ /dev/null @@ -1,102 +0,0 @@ -/************************************************************************************************** - Filename: osal_cbtimer.h - Revised: - Revision: - - Description: This file contains the Callback Timer definitions. - - - **************************************************************************************************/ - -#ifndef OSAL_CBTIMER_H -#define OSAL_CBTIMER_H - -#ifdef __cplusplus -extern "C" -{ -#endif - -/********************************************************************* - * INCLUDES - */ - -/********************************************************************* - * CONSTANTS - */ -// Invalid timer id -#define INVALID_TIMER_ID 0xFF - -// Timed out timer -#define TIMEOUT_TIMER_ID 0xFE - -/********************************************************************* - * VARIABLES - */ - -/********************************************************************* - * MACROS - */ -#define OSAL_CBTIMER_NUM_TASKS 1 // set by HZF, align to TI project setting -#if ( OSAL_CBTIMER_NUM_TASKS == 0 ) -#error "Callback Timer module shouldn't be included (no callback timer is needed)!" -#elif ( OSAL_CBTIMER_NUM_TASKS == 1 ) -#define OSAL_CBTIMER_PROCESS_EVENT( a ) ( a ) -#elif ( OSAL_CBTIMER_NUM_TASKS == 2 ) -#define OSAL_CBTIMER_PROCESS_EVENT( a ) ( a ), ( a ) -#else -#error "Maximum of 2 callback timer tasks are supported! Modify it here." -#endif - -/********************************************************************* - * TYPEDEFS - */ - -// Callback Timer function prototype. Callback function will be called -// when the associated timer expires. -// -// pData - pointer to data registered with timer -// -typedef void (*pfnCbTimer_t)(uint8 *pData); - -/********************************************************************* - * VARIABLES - */ - -/********************************************************************* - * FUNCTIONS - */ - -/* - * Callback Timer task initialization function. - */ -extern void osal_CbTimerInit(uint8 taskId); - -/* - * Callback Timer task event processing function. - */ -extern uint16 osal_CbTimerProcessEvent(uint8 taskId, uint16 events); - -/* - * Function to start a timer to expire in n mSecs. - */ -extern Status_t osal_CbTimerStart(pfnCbTimer_t pfnCbTimer, uint8 *pData, - uint16 timeout, uint8 *pTimerId); - -/* - * Function to update a timer that has already been started. - */ -extern Status_t osal_CbTimerUpdate(uint8 timerId, uint16 timeout); - -/* - * Function to stop a timer that has already been started. - */ -extern Status_t osal_CbTimerStop(uint8 timerId); - -/********************************************************************* -*********************************************************************/ - -#ifdef __cplusplus -} -#endif - -#endif /* OSAL_CBTIMER_H */ diff --git a/components/osal/include/osal_snv.h b/components/osal/include/osal_snv.h deleted file mode 100755 index 2ac080b..0000000 --- a/components/osal/include/osal_snv.h +++ /dev/null @@ -1,139 +0,0 @@ -/************************************************************************************************** - Filename: osal_snv.h - Revised: $Date: 2013-02-15 10:12:26 -0800 (Fri, 15 Feb 2013) $ - Revision: $Revision: 33143 $ - - Description: This module defines the OSAL simple non-volatile memory functions. - - - Copyright 2009-2013 Texas Instruments Incorporated. All rights reserved. - - IMPORTANT: Your use of this Software is limited to those specific rights - granted under the terms of a software license agreement between the user - who downloaded the software, his/her employer (which must be your employer) - and Texas Instruments Incorporated (the "License"). You may not use this - Software unless you agree to abide by the terms of the License. The License - limits your use, and you acknowledge, that the Software may not be modified, - copied or distributed unless embedded on a Texas Instruments microcontroller - or used solely and exclusively in conjunction with a Texas Instruments radio - frequency transceiver, which is integrated into your product. Other than for - the foregoing purpose, you may not use, reproduce, copy, prepare derivative - works of, modify, distribute, perform, display or sell this Software and/or - its documentation for any purpose. - - YOU FURTHER ACKNOWLEDGE AND AGREE THAT THE SOFTWARE AND DOCUMENTATION ARE - PROVIDED “AS IS” WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED, - INCLUDING WITHOUT LIMITATION, ANY WARRANTY OF MERCHANTABILITY, TITLE, - NON-INFRINGEMENT AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL - TEXAS INSTRUMENTS OR ITS LICENSORS BE LIABLE OR OBLIGATED UNDER CONTRACT, - NEGLIGENCE, STRICT LIABILITY, CONTRIBUTION, BREACH OF WARRANTY, OR OTHER - LEGAL EQUITABLE THEORY ANY DIRECT OR INDIRECT DAMAGES OR EXPENSES - INCLUDING BUT NOT LIMITED TO ANY INCIDENTAL, SPECIAL, INDIRECT, PUNITIVE - OR CONSEQUENTIAL DAMAGES, LOST PROFITS OR LOST DATA, COST OF PROCUREMENT - OF SUBSTITUTE GOODS, TECHNOLOGY, SERVICES, OR ANY CLAIMS BY THIRD PARTIES - (INCLUDING BUT NOT LIMITED TO ANY DEFENSE THEREOF), OR OTHER SIMILAR COSTS. - - Should you have any questions regarding your right to use this Software, - contact Texas Instruments Incorporated at www.TI.com. -**************************************************************************************************/ - -#ifndef OSAL_SNV_H -#define OSAL_SNV_H - -#include "comdef.h" - -#ifdef __cplusplus -extern "C" -{ -#endif - -/********************************************************************* - * INCLUDES - */ - -//#include "hal_types.h" - -/********************************************************************* - * CONSTANTS - */ - -/********************************************************************* - * MACROS - */ - -/********************************************************************* - * TYPEDEFS - */ -#ifdef OSAL_SNV_UINT16_ID -typedef uint16 osalSnvId_t; -typedef uint16 osalSnvLen_t; -#else -typedef uint8 osalSnvId_t; -typedef uint8 osalSnvLen_t; -#endif - -/********************************************************************* - * GLOBAL VARIABLES - */ - -/********************************************************************* - * FUNCTIONS - */ - -/********************************************************************* - * @fn osal_snv_init - * - * @brief Initialize NV service. - * - * @return SUCCESS if initialization succeeds. FAILURE, otherwise. - */ -extern uint8 osal_snv_init(void); - -/********************************************************************* - * @fn osal_snv_read - * - * @brief Read data from NV. - * - * @param id - Valid NV item Id. - * @param len - Length of data to read. - * @param *pBuf - Data is read into this buffer. - * - * @return SUCCESS if successful. - * Otherwise, NV_OPER_FAILED for failure. - */ -extern uint8 osal_snv_read(osalSnvId_t id, osalSnvLen_t len, void *pBuf); - -/********************************************************************* - * @fn osal_snv_write - * - * @brief Write a data item to NV. - * - * @param id - Valid NV item Id. - * @param len - Length of data to write. - * @param *pBuf - Data to write. - * - * @return SUCCESS if successful, NV_OPER_FAILED if failed. - */ -extern uint8 osal_snv_write(osalSnvId_t id, osalSnvLen_t len, void *pBuf); - -/********************************************************************* - * @fn osal_snv_compact - * - * @brief Compacts NV if its usage has reached a specific threshold. - * - * @param threshold - compaction threshold - * - * @return SUCCESS if successful, - * NV_OPER_FAILED if failed, or - * INVALIDPARAMETER if threshold invalid. - */ -extern uint8 osal_snv_compact(uint8 threshold); - -/********************************************************************* -*********************************************************************/ - -#ifdef __cplusplus -} -#endif - -#endif /* OSAL_SNV.H */ diff --git a/csi_drivers/dw_usart.c b/csi_drivers/dw_usart.c index 7267e0f..1af644c 100755 --- a/csi_drivers/dw_usart.c +++ b/csi_drivers/dw_usart.c @@ -625,37 +625,44 @@ __attribute__((section(".__sram.code"))) void csi_usart_prepare_sleep_action(vo uint32_t addr = 0x40004000; uint32_t set_fcr_value; while (!(*(volatile uint32_t *)(addr + 0x7c) & 0x4)); - for(int i = 0; i < 4 ; i++) { - if(uart_tx_rx_pin[i] != 0xff) { - phy_gpio_fmux(uart_tx_rx_pin[i], Bit_DISABLE); - } - } +// for(int i = 0; i < 4 ; i++) { +// if(uart_tx_rx_pin[i] != 0xff) { +// phy_gpio_fmux(uart_tx_rx_pin[i], Bit_DISABLE); +// } +// } +// while ((*(volatile uint32_t *)(addr + 0x7c) & 0x1)); set_fcr_value = (*(volatile uint32_t *)(addr + 0x98) & 0x01) | ((*(volatile uint32_t *)(addr + 0x94) & 0x01)<<3) | ((*(volatile uint32_t *)(addr + 0x9c) & 0x03)<<6) | ((*(volatile uint32_t *)(addr + 0xa0) & 0x03)<<4) | DW_FCR_RFIFOR | DW_FCR_XFIFOR; + + registers_save(&usart_regs_saved[3], (uint32_t *)addr + 3, 1); + + do{ - *(volatile uint32_t *)(addr + 0x8) = set_fcr_value; - }while (*(volatile uint32_t *)(addr + 0x7c) & 0x1); - *(volatile uint32_t *)(addr + 0xc) |= 0x80; + *(volatile uint32_t *)(addr + 0xc) = 0x80; + }while(*(volatile uint32_t *)(addr + 0xc) != 0x80); registers_save((uint32_t *)usart_regs_saved, (uint32_t *)addr, 2); - *(volatile uint32_t *)(addr + 0xc) &= ~0x80; + do{ + *(volatile uint32_t *)(addr + 0xc) = usart_regs_saved[3]; + }while(*(volatile uint32_t *)(addr + 0xc) != usart_regs_saved[3]); registers_save(&usart_regs_saved[2], (uint32_t *)addr + 1, 1); - registers_save(&usart_regs_saved[3], (uint32_t *)addr + 3, 2); - usart_regs_saved[4] = set_fcr_value; + usart_regs_saved[4] = set_fcr_value; } __attribute__((section(".__sram.code"))) void csi_usart_wakeup_sleep_action(void) { uint32_t addr = 0x40004000; - //while (*(volatile uint32_t *)(addr + 0x7c) & 0x1); - *(volatile uint32_t *)(addr + 0xc) |= 0x80; + do{ + *(volatile uint32_t *)(addr + 0xc) = 0x80; + }while(*(volatile uint32_t *)(addr + 0xc) != 0x80); registers_save((uint32_t *)addr, usart_regs_saved, 2); - *(volatile uint32_t *)(addr + 0xc) &= ~0x80; + do{ + *(volatile uint32_t *)(addr + 0xc) = usart_regs_saved[3]; + }while(*(volatile uint32_t *)(addr + 0xc) != usart_regs_saved[3]); registers_save((uint32_t *)addr + 1, &usart_regs_saved[2], 1); - registers_save((uint32_t *)addr + 3, &usart_regs_saved[3], 2); registers_save((uint32_t *)addr + 2, &usart_regs_saved[4], 1); } diff --git a/csi_drivers/dw_wdt.c b/csi_drivers/dw_wdt.c index 0fcf3fd..fcfc5b0 100755 --- a/csi_drivers/dw_wdt.c +++ b/csi_drivers/dw_wdt.c @@ -34,7 +34,8 @@ //#define SYSTEM_CLOCK_MS (30000 / 1000) //uint32_t timeout_ms[16]; -const uint32_t timeout_ms[8] = {2000, 4000, 8000, 16000, 32000, 64000, 128000, 256000}; +//const uint32_t timeout_ms[8] = {2000, 4000, 8000, 16000, 32000, 64000, 128000, 256000}; +uint32_t timeout_ms[8] = {2000, 4000, 8000, 16000, 32000, 64000, 128000, 256000}; typedef struct { #ifdef CONFIG_LPM uint8_t wdt_power_status; @@ -52,7 +53,7 @@ static dw_wdt_priv_t wdt_instance[CONFIG_WDT_NUM]; static inline void dw_wdt_enable(dw_wdt_reg_t *addr) { - addr->WDT_CR = 0x1F; + addr->WDT_CR = 0x1D; } static inline void dw_wdt_disable(dw_wdt_reg_t *addr) @@ -197,7 +198,7 @@ int32_t csi_wdt_power_control(wdt_handle_t handle, csi_power_stat_e state) \param[in] value the timeout value(ms) \ref:timeout_ms[] \return \ref execution_status */ -int32_t csi_wdt_set_timeout(wdt_handle_t handle, uint32_t value) +__attribute__((section(".__sram.code"))) int32_t csi_wdt_set_timeout(wdt_handle_t handle, uint32_t value) { WDT_NULL_PARAM_CHK(handle); uint32_t i = 0u; @@ -275,7 +276,7 @@ int32_t csi_wdt_stop(wdt_handle_t handle) \param[in] handle wdt handle to operate. \return \ref execution_status */ -int32_t csi_wdt_restart(wdt_handle_t handle) +__attribute__((section(".__sram.code"))) int32_t csi_wdt_restart(wdt_handle_t handle) { WDT_NULL_PARAM_CHK(handle); diff --git a/csi_drivers/spif.c b/csi_drivers/spif.c index c908237..e1ff416 100755 --- a/csi_drivers/spif.c +++ b/csi_drivers/spif.c @@ -131,7 +131,7 @@ __attribute__((section(".__sram.code"))) static inline void spif_unlock(uint32_ #define spif_wait_nobusy(flg, tout_ns, return_val) {if(_spif_wait_nobusy_x(flg, tout_ns)){if(return_val){ return return_val;}}} -__attribute__((section(".__sram.code"))) static void hal_cache_tag_flush(void) +__attribute__((section(".__sram.code"))) void hal_cache_tag_flush(void) { _HAL_CS_ALLOC_(); HAL_ENTER_CRITICAL_SECTION(); @@ -139,10 +139,10 @@ __attribute__((section(".__sram.code"))) static void hal_cache_tag_flush(void) volatile int dly = 8; if (cb == 0) { - AP_CACHE->CTRL0 = 0x02; + AP_PCR->CACHE_BYPASS = 1; } - + AP_CACHE->CTRL0 = 0x02; while (dly--) { ; }; @@ -154,10 +154,10 @@ __attribute__((section(".__sram.code"))) static void hal_cache_tag_flush(void) while (dly--) { ; }; - + AP_CACHE->CTRL0 = 0; if (cb == 0) { AP_PCR->CACHE_BYPASS = 0; - AP_CACHE->CTRL0 = 0; + } HAL_EXIT_CRITICAL_SECTION(); @@ -178,6 +178,7 @@ __attribute__((section(".__sram.code"))) static int _spif_wait_nobusy_x(uint8_t volatile int tout = (int)(tout_ns); for (; tout ; tout --) { + WaitRTCCount(1);//increase polling interval status = _spif_read_status_reg_x(); if ((status & flg) == 0) { @@ -188,10 +189,77 @@ __attribute__((section(".__sram.code"))) static int _spif_wait_nobusy_x(uint8_t return PPlus_ERR_BUSY; } +__attribute__((section(".__sram.code"))) uint8_t hal_flash_lock_status(void) +{ + uint8_t status = _spif_read_status_reg_x(); + return status&(FCMD_DATAPRO_AREA_512|FCMD_SRP_REG); + +} + +__attribute__((section(".__sram.code"))) uint8_t hal_flash_write_disable(void) +{ + uint32_t result = csi_irq_save(); + uint8_t status; + status = _spif_read_status_reg_x(); + if(status & SFLG_WEL) + { + AP_SPIF->fcmd = XFRD_FCMD_WRDI; + SPIF_STATUS_WAIT_IDLE(SPIF_WAIT_IDLE_CYC); + spif_wait_nobusy(SFLG_WIP, SPIF_TIMEOUT, PPlus_ERR_BUSY); + } + csi_irq_restore(result); + return 0; +} + +__attribute__((section(".__sram.code"))) int hal_flash_lock(uint8_t area) +{ + uint32_t result = csi_irq_save(); + area &= FCMD_DATAPRO_AREA_512; + area |= FCMD_SRP_REG; + if(area != hal_flash_lock_status()) + { + SPIF_STATUS_WAIT_IDLE(SPIF_WAIT_IDLE_CYC); + spif_wait_nobusy(SFLG_WIP, SPIF_TIMEOUT, PPlus_ERR_BUSY); + AP_SPIF->fcmd = XFRD_FCMD_WREN; + SPIF_STATUS_WAIT_IDLE(SPIF_WAIT_IDLE_CYC); + spif_wait_nobusy(SFLG_WIP, SPIF_TIMEOUT, PPlus_ERR_BUSY); + AP_SPIF->fcmd_wrdata[0] = area | FCMD_SRP_REG; + AP_SPIF->fcmd = XFRD_FCMD_WRST; + SPIF_STATUS_WAIT_IDLE(SPIF_WAIT_IDLE_CYC); + spif_wait_nobusy(SFLG_WIP, SPIF_TIMEOUT, PPlus_ERR_BUSY); + } + csi_irq_restore(result); + return 0; +} + +__attribute__((section(".__sram.code"))) int hal_flash_unlock(void) +{ + uint32_t result = csi_irq_save(); + + if(FCMD_DATAPRO_AREA_NONE != hal_flash_lock_status()) + { + subWriteReg(&AP_SPIF->config, 14, 14, 0); //disable wp bit(14) + SPIF_STATUS_WAIT_IDLE(SPIF_WAIT_IDLE_CYC); + spif_wait_nobusy(SFLG_WIP, SPIF_TIMEOUT, PPlus_ERR_BUSY); + AP_SPIF->fcmd = XFRD_FCMD_WREN; + SPIF_STATUS_WAIT_IDLE(SPIF_WAIT_IDLE_CYC); + spif_wait_nobusy(SFLG_WIP, SPIF_TIMEOUT, PPlus_ERR_BUSY); + AP_SPIF->fcmd_wrdata[0] = FCMD_DATAPRO_AREA_NONE; + AP_SPIF->fcmd = XFRD_FCMD_WRST; + SPIF_STATUS_WAIT_IDLE(SPIF_WAIT_IDLE_CYC); + spif_wait_nobusy(SFLG_WIP, SPIF_TIMEOUT, PPlus_ERR_BUSY); + } + csi_irq_restore(result); + return 0; +} + + __attribute__((section(".__sram.code"))) static int hal_flash_write(uint32_t addr, uint8_t *data, uint32_t size) { uint8_t retval; - uint32_t cs = spif_lock(); + + uint32_t result = csi_irq_save(); + //hal_flash_unlock(); HAL_CACHE_ENTER_BYPASS_SECTION(); SPIF_STATUS_WAIT_IDLE(SPIF_WAIT_IDLE_CYC); spif_wait_nobusy(SFLG_WIP, SPIF_TIMEOUT, PPlus_ERR_BUSY); @@ -200,13 +268,14 @@ __attribute__((section(".__sram.code"))) static int hal_flash_write(uint32_t ad SPIF_STATUS_WAIT_IDLE(SPIF_WAIT_IDLE_CYC); spif_wait_nobusy(SFLG_WIP, SPIF_TIMEOUT, PPlus_ERR_BUSY); HAL_CACHE_EXIT_BYPASS_SECTION(); - spif_unlock(cs); + //hal_flash_lock(); + csi_irq_restore(result); return retval; } __attribute__((section(".__sram.code"))) static int hal_flash_read(uint32_t addr, uint8_t *data, uint32_t size) { - uint32_t cs = spif_lock(); + uint32_t result = csi_irq_save(); volatile uint8_t *u8_spif_addr = (volatile uint8_t *)((addr & 0x7ffff) | SPIF_ADDR_START); uint32_t cb = AP_PCR->CACHE_BYPASS; //#if(SPIF_FLASH_SZIE == FLASH_SIZE_1MB) @@ -246,7 +315,8 @@ __attribute__((section(".__sram.code"))) static int hal_flash_read(uint32_t add #endif - spif_unlock(cs); +// spif_unlock(cs); + csi_irq_restore(result); return PPlus_SUCCESS; } @@ -254,8 +324,9 @@ __attribute__((section(".__sram.code"))) static int hal_flash_read(uint32_t add __attribute__((section(".__sram.code"))) int hal_flash_erase_sector(unsigned int addr) { uint8_t retval; - uint32_t cs = spif_lock(); - + + uint32_t result = csi_irq_save(); + //hal_flash_unlock(); uint32_t cb = AP_PCR->CACHE_BYPASS; SPIF_STATUS_WAIT_IDLE(SPIF_WAIT_IDLE_CYC); @@ -268,15 +339,18 @@ __attribute__((section(".__sram.code"))) int hal_flash_erase_sector(unsigned in hal_cache_tag_flush(); } - spif_unlock(cs); + //hal_flash_lock(); + csi_irq_restore(result); return retval; } __attribute__((section(".__sram.code"))) int hal_flash_erase_block64(unsigned int addr) { - uint32_t cs = spif_lock(); uint8_t retval; + + uint32_t result = csi_irq_save(); + //hal_flash_unlock(); uint32_t cb = AP_PCR->CACHE_BYPASS; SPIF_STATUS_WAIT_IDLE(SPIF_WAIT_IDLE_CYC); spif_wait_nobusy(SFLG_WIP, SPIF_TIMEOUT, PPlus_ERR_BUSY); @@ -287,15 +361,17 @@ __attribute__((section(".__sram.code"))) int hal_flash_erase_block64(unsigned i hal_cache_tag_flush(); } - spif_unlock(cs); - + //hal_flash_lock(); + csi_irq_restore(result); return retval; } __attribute__((section(".__sram.code"))) int hal_flash_erase_all(void) { - uint32_t cs = spif_lock(); uint8_t retval; + uint32_t result = csi_irq_save(); + + //hal_flash_unlock(); uint32_t cb = AP_PCR->CACHE_BYPASS; SPIF_STATUS_WAIT_IDLE(SPIF_WAIT_IDLE_CYC); spif_wait_nobusy(SFLG_WIP, SPIF_TIMEOUT, PPlus_ERR_BUSY); @@ -306,7 +382,8 @@ __attribute__((section(".__sram.code"))) int hal_flash_erase_all(void) hal_cache_tag_flush(); } - spif_unlock(cs); + //hal_flash_lock(); + csi_irq_restore(result); return retval; } @@ -376,6 +453,101 @@ uint32_t phy_flash_block64_erase(unsigned int addr) return hal_flash_erase_block64(addr); } +__attribute__((section(".__sram.code"))) int hal_flash_rd_status_reg(uint8* buf,bool low_8bit) +{ + uint8_t retval = PPlus_SUCCESS; + uint32_t result = csi_irq_save(); + + SPIF_STATUS_WAIT_IDLE(SPIF_WAIT_IDLE_CYC); + spif_wait_nobusy(SFLG_WIP, SPIF_TIMEOUT, PPlus_ERR_BUSY); + + if(low_8bit == TRUE) + { + *buf = spif_flash_status_reg_0(); + } + else + { + *buf = spif_flash_status_reg_1(); + } + SPIF_STATUS_WAIT_IDLE(SPIF_WAIT_IDLE_CYC); + spif_wait_nobusy(SFLG_WIP, SPIF_TIMEOUT, PPlus_ERR_BUSY); + csi_irq_restore(result); + return retval; +} + + +__attribute__((section(".__sram.code"))) int hal_flash_wr_status_reg(uint8* buf,int len) +{ + uint8_t retval = PPlus_SUCCESS; + uint32_t result; + + if((len != 1) && (len != 2)) + { + return PPlus_ERR_INVALID_PARAM; + } + + result = csi_irq_save(); + SPIF_STATUS_WAIT_IDLE(SPIF_WAIT_IDLE_CYC); + spif_wait_nobusy(SFLG_WIP, SPIF_TIMEOUT, PPlus_ERR_BUSY); + + AP_SPIF->fcmd = XFRD_FCMD_WREN; + SPIF_STATUS_WAIT_IDLE(SPIF_WAIT_IDLE_CYC); + spif_wait_nobusy(SFLG_WIP, SPIF_TIMEOUT, PPlus_ERR_BUSY); + + spif_wrdata(buf, len); + spif_cmd(FCMD_WRST, 0,0,len,0,0); + + spif_wait_nobusy(SFLG_WIP, SPIF_TIMEOUT, PPlus_ERR_BUSY); + SPIF_STATUS_WAIT_IDLE(SPIF_WAIT_IDLE_CYC); + + csi_irq_restore(result); + return retval; +} + + + +__attribute__((section(".__sram.code"))) static int hal_flash_config_srp(void) +{ + uint8_t retval; + uint8_t status_reg[2]; + uint8_t status_reg_len = 1; + + FLASH_WP_HIGH_LEVEL; + retval = hal_flash_rd_status_reg(&status_reg[0],TRUE); + +#if (FLASH_STATUS_REGISTER_LEN == 1) + if((status_reg[0] & 0x80) != 0x80) //SRP=1 +#elif (FLASH_STATUS_REGISTER_LEN == 2) + retval = hal_flash_rd_status_reg(&status_reg[1],FALSE); + if(((status_reg[1] & 0x01) != 0x00) || ((status_reg[0] & 0x80) != 0x80)) //SRP1=0&& SRP0=1 +#endif + { +#if (FLASH_STATUS_REGISTER_LEN == 2) + status_reg_len = 2; + status_reg[1] &= ~(1<<0); +#endif + status_reg[0] |= (1<<7); + hal_flash_wr_status_reg(status_reg,status_reg_len); + } + + return retval; +} + +__attribute__((section(".__sram.code"))) int hal_flash_switch_hardware_protect_mode(void) +{ + uint8_t retval = hal_flash_config_srp(); + FLASH_WP_LOW_LEVEL; + return retval; +} + +__attribute__((section(".__sram.code"))) int hal_flash_switch_hardware_unprotect_mode(void) +{ + uint8_t retval = hal_flash_config_srp(); + FLASH_WP_HIGH_LEVEL; + return retval; +} + + /* cpi api */ diff --git a/flash/PHY6220_Flash.elf b/flash/PHY6220_Flash.elf index d6b5a6f5058ca7c42189bf9144dbd348f68ae0a4..c9ff7b2eaffb340f85bdb3bb1d0c7eec46999e4c 100755 GIT binary patch literal 81844 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 A9smFU literal 79664 zcmeFa4R}=5+4sBmOeP7*5CTasd{07! zbMGY?sc!Pz4v5YTUI$oRaM0}Ov)*R$YDD(rU2*U0^yfYpxEG^t)wc0 zg})L5PlTaQV1T0Rs8p0V5<>3(IsT)8|7hU<7aE{;e&zp-&qc}V9-GIPY~GXMX-U4l zJwEyQtEmqt>N5L_x^T6}=0JzBp8AO$E6$9G$v!jYV5-tTD@N&`5aUTMO;+s1Pb&FK zp4^nG>{lGq6*XS5Bj)6W9dxF!_bZAWzRJPW7yTvvL4KwGBjNH|YR1vigWj2%9G|nu z+-jSe5Wl_H;Y#s$A3ZZj>9?uX-tQ6>`(_d9GjvWQ>t(YhOQZq$ucl_e^`v?1CyL|Z zJLB^mQysfv;}<2H3f4cN=FfYwVQb0dj_HnFrxN|i=6uJK@sk^NNjJyTxOgR>;?8^0 zlk9j>>HoD^O}ztoRrV;3gQ;1m%4Ac%lIPmhu*+gs`d>0nS4{b?!&$cdEsp7@5^a;+ zyWAp$5~MI&ZP@(I^wWdXyriQEiqe0(Iq7hs5|c`0r+oTUb1S9pm>wTLD5hbnGC`vO z)-&(@=}dBqqws5#m(m|BzWSQjD@JX7PW9`2R>$`pe8p z{%VusNljl$|1fiM_;09}Lns@$y>#c;PfjWg`^MRBbvS0+TDhxecTudh+5F2Vl{ zl>PzcRp#ijA2B($I{l7me@CvqGb#D&%raMhHob{F!L~%6%&m{yd1*>?Ik}#yQly?H z>3ULAH>Z-0o-&zR&CuUixPO)Cm|?aihrftB^WKZ6lf$2$mB!2=Kb*$WAu^5cPiu8y zq_I*@<8!$4G=6ec8n@he;eU~WbFfU|082sXpJFNzWq2O0Une?>%+}QKmnehxbZS^@ zQ)k|L<;3lemF~U z%ouOYF5X`;_Ndu*U6EtzdZhT!Wkcf~GX`4|Ta`<1aV1|#`Xdb~12+E^NIDxoStQTCI*v-JTUzb(6!> zY;`X?)UeUxw(jw`tZIG}@>R0WW^)vJ;)kUul&?aUb-&+z^n2Te;wI!NqNdGF`nJMv;&uX#&d zUne$h-Pf?t-ypuxyC5Gw+v=FMZ%}+GS=FZRpNmTxLMg|WQrhHp)AvusB@Fp3KEHu3 z$Zi@o?eko0b>Vw_yqZt7tCco0e)M3iw8Qk$W*2)TBNxma>BtB$ctCKYu z%4G9Co0aVDbR4x4N+H%7)O}+xMp8RL+dI_&i;AJV7Fzu=l>05@^J;2bD@G@4@l+o5R&!N=Q$!FfX671F(Mk-Xkr zE3X@t%IgPM+yJ|-WO7;{=YQvD#C)a}pE>wU!zUk~i}CT}L-I^#35^9;wXD7*Ki__q z&;NVqURh|*|1XkTQZPiR3HavtU7?o$BG~_7uXwS})K{j16(t^v(f`9q{zv?OH1Hn{ z{6_=-(ZK(wG%&ZMWST9zc4B#1ajC6jV$EgCY_;v}{*Z0SOORpSfjCx9g&VKzI*3WBkru4V!+^e6r;Y{)N=v+EZOYacQSh*$lx~MqxMj>DFam8{ZZ7VA~anp z11+SPYjLG(W<2ynnjzJbxz*y@q{d!=luahfI#Q%o?3l^q6K^>HCzBeVCIZC$4JXTQ zDbz$C38m<AqUQ347R zrc$uc0*Vs0lg}6dj)a#9YywIX+wv4shUqtODo=2eN2c(oN~k6nE1))EF+rAqy2Q48 z#Wc?3fokd#22&~*3Xg^al42S!z>_eYAX`97LLz1JA_4w{i4^Bz0fB_i2qp*!CtO9r zas+fGd`U1-z}kdzf?NUX6Wb;$rb#BM{_cbxO2#fcHYMyOVR-_!B(@dcE~RNV{I@2I zpy-oLRN=h|K?+qMU|YiTi3HR?k+iuz}gbB!T5 zNv)@ZnuS~%$Q}`L?~TZ9CPCEyX>tXgjL2;!If;;vqHcsH)fG}MP*E2PxmzKVWUD5zO;tx~3l(D%aV2ElVVfl1TJ=qo!S4C%+qS`4`fsxGc4-t?IfI2(1 zN0|(PX5|RJ^$zh`q(U8H4xCKm0ai6(0oc3(*J>hND&_!PTj@H+Tt?Re={jDC(Kp?okn4{ z#Wm3NP>P$a#@#}YPJwdNxEg|C1a>uU0m1N80G_hO<8BA#gvPP~U*q~Sd=lvET5^7l zd^I~3z9d5Uj!_b|u71EM1j#a-uT`vt5N{eng~9lSZ$)`z2&t_TDd=i@9l9p9ky>dK zT8rrV7+^k$=&?hm!c$dav?MG<#;BkVD)BKVFos7DKC#b`oUs%-)=s_`-+)U?h+=Dl zP#ig!OkyO8rIE-qaU2C9%Z_`H{Inq`K8BoQE_e^$1JW=Ut{<=z-`5S8jPL6Q6hin7 z1IFOGd%&9m6y-)GAttsAXildXi6hOU=0mvE1V8g=60QvNws{ou7`l$JeuYVj*+$p# z)@Pv$a|T^otxY5%ldhAk6UlunU8h=KqU$UwN4gUGGDRMD9FQ1ezW7?ClXNTjPoS_d z>KG-7tihb4;b`c>LD`sChmcyi%=Vw*dcfO=r3`ozgTJc8u0fH^lW&20?3W~MI%#K6 z%yaloRuAHPa0@~YrihfTBNnxpbPRQ6E{>%8E5g|VO{0{gMU>GJ%@>of*aehCDaneX z*!uXMxW{r$BhX5>S}f}xgnY#sOV`)Zb&T~cx?WE~;;n@cX}ONvi>yyWoaOo-!QG(@ zp;UsnOrb9;$tKGkLLn)Ha2}&rR^vL>LjrFYh0DYo%a#kxi106H$a0sK_BV8Wx0d$H zbiI|X3XEqMAr|{war>d z$^VqDv#d?z-b>fnO6+D5^x!?nm&kW9GA8n^DwaH4r|z^QndTx)8clXAgT&aSq|s!@ zk}M!5jV3#m!2;sbXtHA&BEXtPlO0QnfaElq>{wC-q^8ki$C4%>J&h(imZ1VhrqN`_ za)AI_8clXA=>oFSXtHA&CLlYFCOekl0&>!5vSS$`z@A2v9m_}o1!*+dv5XQ>m`0Nw z%V+^bX*Aifj1k~SqsflNCZKdECOei4Q#}e@o<@@$OQ!IsN~Jq(rBr_p4`a-r~ONTbP)WxN1S8clXA*#cV9XtHCuNPs_WBE`8_Kp>4KJC+Fo z!f7fNKICu#O?E7on&#k?{xBTWTSXF>Y)b5C*sfY|KY|aTI7jgjnStErDcmK8;9@b;t^Q%xp{=TggQ0=pY97Vw zHK{ESPU}7D^wpjYgcxyv;`NF(P#zK)aR^NgOc`8A8HmRk@hGBvgpaz-v>b6p8LW)X zhVL=>94FsC(m^kN#g*+gPZcZ8MEOA{64S$OUx`S+SKSAePSBn=H$@1pXoGpVzY zn~exTIl;^dq~&6r$i-_AHdf@KTjV0^2FlTmCJLukK^WD`aJ3Zat1eBCr4U2{)t;Y3 zgt>&U;|Qx2$t{FULmiBJ4Vr31@Ft3a=ZVAB06H=CQcV~w&Pkx!b21|AQX#Axkw?4; zi3m!)>@Kh-e5w#mv-;6}DDqH5A5J0`nKFMPR4`nZ6+h)QAcgk8DNjny=m{2vEvS@=?=DjN;U9q;$H;Ux}{#UkRi zj#fn-Ah-!U=C`N~HNn&cdG~=wmO~!}$j(g4QmSbm^qn1o+XwK>ZpOv8ba6Q@tca4L&9iiE!fVeg{wHq%I?n@RFTSPz0^QdmvyE`-@j;l`WF z5l-Zz(~x^hB+z-jK}h>Ku`uu#MV`b-@qgDbzDp!*PMBnJLXj5 z3&)@ss{P^Wb}G+ytvor1PGwSiejF*!cFn4g87;*pMT*&AL_UOS#S%*dIfz?TBtY$X z4UsSOdAi7}1>vS6@Wg#kBAEI?b&=LOZx^B<=GRoTwW>-p8M@;|qST&r! zF}Zu;bpRi&kooY1+EsXe2QXfDyskwTA*Ha!+Nn$P4Zm7-_qUQ`m)DV>^QKhD+F3zBl)hgtuwT0UHe~?yxIS4#O z$vuhKv51}3OIjSLIuOrvM?g`gs?$gv--^(5^Y(3g)SjmhZJMa5Z^t3%<47%CB>8WV zV(oNF@f0;2b#ak8ghZSnt*AX(dUrueA3o_Kz3(0H(vuVS2tE|a(LLieBDt(2Be@SL zIeKYHOYUQq+$TnIKcU+BOeB|xh$vn@q&OnU9g8G4L%VaZThqnQ5O}62)NT?rQ<(K` zvg(g`Gu(e2#(+qj{>jmo6PQ3!jjp{+Up5+(nEY>s4VD#k1V-dR=(I zMAjk14DB|`5X0JES#5aU?*7Naryv z3nRe8gr;{m5Jhq1L>!(H4qC2uX}K!-0|~rW%T6akmNxmD;XtX){3+Shy%cbmn6C7Y z>#zr@g6|ii%CgDc?+}(p4+S0;H!iK3VKqZ_AEi{?0Imy2tg|va8ZPdc`I>&>DFb7aTc#mmH!edrYP6r z!G_v11P|-8e+Q?92%Y^0Ty)XJtGJ*QWX=&>*gin;Q~2~EjfyjH*$FSjmOzh2@Oc`} z^9G58T9jNnTu62$$xxS6l1z26NaICBi}=s$Ml`k7HVW`H7OW^b`_-7a6LP6DKSK{I#T+CaF3$=D$Bb}Da^V4bZ{A`43 zLBxuU;2H!|YzH9mFg_2!Ig{jNlB`UUlWX|pIN+Hxm%bL@3$flsjFb301*}+$uuUW^ zS3%Y&dlh%XX*D@13#hMjpmU<$6Eg_vr5kWbkBHQsIE>O_0<;l<#gycybU~AzCn)*? z>hvinJxNk~7Q_STk{&2Q7!5ged6&TDB#fp3FOUqH7#zmMyw7j}E136hoG~vhr?HG4 zMA7J`_HO0S$oOd9f@7M@$klji0FV6VzT8mf20V~_C6o&X$A9=Q9aj!Q~O zG$)NnS{yrAO-3hUDp1Tx(-NmAR;0|bnh?sIr6eZKL>Ri`qE@7+DOmPoC>1G_(EMU` zPt;{xt~$$VL>;USQ5}dJpQtW|&;i`92)al}KP!2PAd;7<83{vn%oL=DWQRubhNLeP zZgEDQ;zgdQ%qePOB1&MPoF)v^qF5?YXwH!cj3+-0t-3%UR)V>TEPxGxlVq;PTPsqu zGLg_h7EKCtWJ2kZfx5~_VS@)jVI**fjL&1IaA#6RDk&q434zR^vKlCf3xJewAvZk{ z^)>`EwP8HR81-|NJUy4ubt@E`qMDP0UJ|JYW?e53NP3BpYPX1h7D|i)#_Af=1IDp< zsQ-Aa5-=Ok3?sp)ghXi=R#_CyqPW?euiklh(vOij7=lGJgjj9}aatbYV^HlCDMr2r zWTR3>qG%YF5~=2Os}O~Ub+@X0SyV;1Hwi zDMr~-xdEo>!gPxpswbu61>6ABWx>gghDoHlHCmS?+7?IXb_0QAC?iLynhn$?E)xx4 zRHC98%V_R{<$^9xZKR(- z`KRj{g3(gxie$8k6iw0$=|qyWd}8fwNWpwd%D`xqs8T_T=_%4|8P$kbl8YXInunBC zs+SH~P?R$6FFU(A(pfsrmFZGdmgnkL=SZL&R8aMi`#f=h!d*s{J`ygKqW0l3pK6){ zFW|k_LMaH!ufoTq&_frK`fs#KES69-h1RG_tIOAx>jvSlnCK>(`BF7=xj8A zZcYi$7&&9)vJoxjHMW)!mzh&+%_h9?s2)OilX44vpDoift=>Hmudvj+JuBd__t3wlgZEk;u$Ezrwpl_8osAaI#-Qf(h ztadhbv^ILZxh<6CP}qZaCU8v!LILREoHt3T2Y$Wnrj}bnoKBHCB&GNIrRPCm#ay8@l>4JLs~Ax%c!N^ zRk~8+aO26O&`TBn19|`3dOBC-?vM|9^*J>K)<+Z?3iz6|tZ~(Of~%b5L*+p+upS~8 zZ!p-_uHpG~Z+Ppfr^&qeb49gJnvpp=Gh;?x{Y-oPq|5RqU2eZ2Hn%Rf&K5gk*`%3y zqsC_b)IMX}#EiV$S&tbW<^fIS)wwP48OvX`&zf@~jBR$tq>_BIKi8a^J8Am3DU)W* zHv8&+U1c8pj6EkaGZHVM$=sED*>cAyC!8}P&Jbrf&xm%Mfv{$4UB;v=`olR4UMH@kDqH(XmZ)4Wy9HGj0uHpzUqYBPVl z&W3YtRt5@8%WhZp6J8!)JSaC8I*+~FoM1CQe@(7=w<)(fBhQv$?zv{3`3qC7 zc>^3z;-!uRG%ef~MKd^qLsd*`2MtV8@Q6;QcNTqxzl5LtV=~aVtUMv*$#dSti_{8{^&C!@eFr*eIc2-(}+d!>6M0D z;co3V->Buuh(qsXa9NaBibF4e@I27F00y63_EQKi*1$LwC&hOoh2kV@OA_Uo@<9Hy zKAtE1QC29ZF)2o|>3*~VE)af3+}ebs_~OLbkYI$N<)$?w>A|RDLm#w`9BQ~jY30y|5r-C*R1ZcR!<|-;T$bTZOG)ld_DE^dnv&km zk##ap)QJ&~mXAE1;Z94+^SRTC66-!gp0H0!XBXTJ+aRXJC9xro7Mi+U&Y}2JHVQ{~ zj_VoI4QbL(w(d`Nw{OFBRC_{wUM=dgRD2s@=^0A`8rxZ6v(|`EYsI&bAA02D5pspS zMe<3Hfy$Y?kxzQoMESDeL;0o$Sp_&Vy$XA+gm#TI=#g8F45KtV#i&$Ks)%z*i`Ts} zgaS#~buE;nU{!ib;`DifK%{$6LR;-EGgaPpL<|jM8f*fM-vjmC1r!o zcox+hZoviK7%TR8g5FRF(A3f9Hp=Y_lm%TOui|U-_<~+{*ctRFp`feP+2r%%7iHd6 zUcdC~3@U+kID5MS2&}ZY{F)k(9%MK}h>v82MyrDD%@Ctd-kgoTu+rpi^*B3&9#`0< zgj(8zVH>@c8t!t2Tac}mcE3mQc>S)`io3n7$=9qnL#tbZ?X6-0q04vq{YnR7P0n}f z@?0pB;%{$jwuvv2C{nNW;te@1QzA&Dbe%zGC+aEK>I$yZf>yL4b3t#bE1-0=g?!Cz zUXKkE$RKiq*$ecncv@Y~fH&w1v_K-$M$qF7gcb?;7 zWHgcz0F*{BVgzSL< zvrvXJ=xS?5L1^N)xJ_u7*8tO+2%=e_u(|;BsT5Z^YpN>dIBQ|yrQRl`(cg~NsRX&L z2s>=j)gm=WYSYrKrYoV)h#GYZCmlfTksMLhsR~8@l{u7Y^b6vQ8MhBDS6owWxNAtM zay5Hv$U+bd*`qQqpjAXLq|~;DU4G$LLnfkBY7G$q7r0ub7|fX~Ld9-(sc3r&twV%H z&Dd==XFRHJ6gy!`IjO%7!2>p-VvZ!5RednBXSxt=oba@Fpzl&hhFyH; zMXO76Anuh?dI0wd&aYDpRN-K|UoT~KO|8fR^*eLK3Lb`{DZuE*BK1Tvr6NRY4trYz zP*KPm#89sfg--WsH}V=)ooIuyWoyRU>GDBY?bM2#U1!_AsH|umYom)}Jo9XJJWTBTj$TO8!O03TIZq&X-`EiSYO5vL_^S}sD>(n%Lb zCz_C}N-dq5#bs3sPLvQ_@hy%*d^_+#7U)zWE+fLpcc$h#AJCk7ae64)m)@`QYEE?O7MHbjx=C}T(+16zPPb^T zbRxklV{?H2&q(UW(}VBuflBFAq@_crnc}jFPLy$$I>n&}Trfj=Wm@x%DEi(14T<#H z)ED?57j&X`$5n;wSRCYgv2a?HkJCJHS-SwIz1k(6_KV9!bo!g-N+(THByS{%UMp9X zYC6$Nb*i$IBweXpN=Zv)bozBmBqQ_-0#&J@lNNn3MPDJJFQ!viT-MNuq?wdE8l=?4 zl)t}dA?QSjPzaeA{bE8Khmpb$>x2|BLz6@4(?cNSicT%~n3Q#f7-cw^<#dAxxtLCR z_F5=UlmS(VBu?Vb)eebXCju^|(=GT=N_5^SoJH|8Q4ysTz(-Ht$dhzBPpC*obXK{R z>!}$+$eY|yf#*6!gizk@5}_hx+XZ}1I7Rvz=@c;)Ln%}{hJ5KJ)mw^c>J>IowFjp^ zXqPYHbU?fOGfoG!OG6ID=@w3lZo)~6zJ#Lh6Ru0>^qRPgk@vtRQyBJ=`(9_>W$)h{^Lsa7~GqSG>b zOv+V;3}r2zc07g;Ql-<=;<9!(PW!Y=BV;;oo^Yz76aAh5{bwCc4ces5D%>1o7Konc?%K&<2s$2(gi3bpyAZ>-4m6TJ$zf?`xNIg4U7uNV}%EJB4qx3|MUh z!jQ<1RH^M2Bml%jo5lKXx8c@}ZqUNKVe8MSG5fn;uinP47a9ST7k(@RN zr$uzSOI${Jq^&^u$powNZNOh^PIP)&Tt*`720p9#it58xDxQL*<3oRyhkj&jxYN@S z&O1#GqLGyRB*9cFrujU8qsff3~g4XYyFf{EfJDrue_bnb+@&V8ec?zW)l|s4FoU z;lBW162un{;tP$PDPGeLr8m%ozg^iY!)Jl_bV^lU6g~|8NY^g$X0SgQLU9m30p9-=_lHKOdl?A!El*gJ6Jp%#)BjK!%j}G&qad_wT{!9n$|@aCS(t8AHMjmVOTSrm*y%2R`+- zWLgzht&&Vj>Z&H0zdrCW7M~XIJ6B5oPrx?jAA>j5hckP-2)u2zl)ng^&dS>i-pTBP ze(y1oe$a}8^nEY5oP~c1Onl1solnf|T>A8|&3n zU>hr642I}bW-saB>^U;MeDJ;jQeG7}{*d%<1$Q%f*Mn1sNqyV{KC)WI-wFP1jg0>` zc$+?@qw;+PwzKw-f+@p(X8$?hU0=%hCE%hm$@Soa)JfwYd7a>Gtbg4Cw#}B|cYx!6 zA$dP|dy35e2jD(dpD`F4`toJ?3&3kxd^?za2Tlj2KOfx9?3>1xt;~L}2NyAY-VN?~ zUdG=IPS#hmBoBW*SlPkq>l<*@uVwgDOn44fOQyH(x3Kz|N&foWo8&DAk7W8@2R`zU zjDI)y6w~i-!T5`t;-L6%fVV#-`7~I0Rq}AuUH>G>^gE~WJ(3rJ_kShX2TskF_16s! zu>Rr!@UvIT@GpU5==DwSGQ0d!+vsa14w82>9S(>HmAMo&Gur4yw;X;A9s5pWqX$e~TN8_Ejw7XMn@3 zzbgQj&z1fQ!S&xt_JVh^`PN#n!oqI`A7SIyqu}G0%J?sWYnvp$1>Vo*Ti<}UxukzV z0QH0U6}cp%J_Zee{kWxnHn{#q$z|ZWS(4kpg%?Ww{1|+=MfyJk{-{LqZ^6CyNq!Z) zpB4`|NWaIx8=1ahQ;;9lo<6Pp&Cvhn zXSRb!qK~J8!v7BJVg19Oz=v6Tc^ABq%|E{a*S;d-k4S?YrvJ&{mN%t;Ik=X|bAmr& z{lO}5>6bG6W^hlDx%Q&FbeU_~c6Ie+pd1);q(7p?=wXW(qi- z)mJTeCmX+4fcO1Y%DVv^X6f~U=hRC7Jzxj3=fmJ0rjLJ;|6&!;c0Z zyIpb-IOkuI8^AqROTGzwoYmjG;JRtj|8e4C$uEKnSbu#KT#7j^9n{}^NB&nz9y}85 zt5othu;P*BDI$OUomIL&jeN?tW47R`4!1KYkS4z|#9YcXM+#1{(c#FAM0;hz(-hptOp-p^6v%HAG5@=823*s zN+0;qRM~$&3*O4w{~>VQO)~v2!2#Ak4jqm8AhX9DaKm>pd@(r7BK3VaxQ?xd)`AbR z{QU&n|GkX=Bsld8$p^soosv(2dH)+vGXa*LQQ(cNJePt!pUL>u;24`^Ke%DN?I67`fus~V{pSSB=>=LviaCPa5?KAKLGDw10}daR@&e%PPfGp?_yjA@ zPVfe{et8*ulx*E8^`D|3uineU;=H;L;V6 zX>L|jD|tP*pUrO`1P7RX>;i9P11o0Y#6Y-ja-12~!4(+3wIKkWI@eege&Cfncdz=iW9{{y^@>4*N7e&Ab~ z|KZ@>to`MIQ<;6v2jd-naZvf&!G{J)z72ew^-m9jH!%Bo1{|0p^YeFbYQ2pA8Ti=4 zlFb;q8$OgwKMLISisTvK0Mqwka38C$72ug{{`@1bosHj*fOD#)yywAuzJ3UNggu`+ z241j6=KnOrm^lt!P&-4=lr?d981-zD(_t)UM7@7V) z@E;sf-Vt#2FC>2pE@kNt$J+ZKoA2j>cQgIY0gwE-jPC<~w^j0bu#JtE_k+{fc=-aj zklD)-a1rZIRGM3{@{I;3zbfTV1+QY|tp@Y<+YILSPuGHbS^u{g-2a`F*9ZPJ)9*9j zqXFsv1~KdZPl7ij%Km*Y=9*hs`^X0Wl$CE9cqHRR;O#8E7OvNmCt3e?2F&j#r%gru)yVJ@!F4H;OTfo{lIy|AU6QW>JK`m80{`tQ$&Z4c zo+?G4iZR&YN{ ze;c@k%}<^MuV?z`%fR};Z`hYbc@zFstUZ4P4zT`XXc6??D$~mco7ng_AH0CIXAii5 zmG^q^$hTztt>7cfULFP4v-R3Oa17J`2NXUe_GkEKGS)bd%4NWrqUhrWyp1clTKU?~L0?uajMK7?eXZ1B0wo3aW(n0Cx zf&19{V-7fn^^c9u3SLvjbWE?M$M@SeGne*w;A_4mKP#`}o0etHQU7$o)m8JOSS zig7^Jr&8X9;KQ&1I!J$I4uo$JD7YRRMj7cK|J4qZkLBk+@JH-^;FI75EPwmKeXPFT z06)goYhQtLmMh{Q`ANm-pP7A)10O`6NC){(2lq1ja)M8=_R|SI!t7}yxQNyNFTwHn z81kOOb(p31I{3&|>HjIXkUbw92;1CtO8SonA7S-d47RfIp%%>T#{+(d>1PeN!K6m= za~t?3=KoMebbrzZ|8Azw-+^}^k93fJ-Tn#*W{TMC;W}Sok8vITJS-p&j-PEL7CnjaL*RWZ-9>! zOa2UOXZDj=hVcOR2z&6$&R)Y`SBGc~zf57x{A9yVrZ+-=)?ZILYh3fYS za1XP;KY}-0C*^$rUVn|`fvBs(cO+j3HvTpW)z3`up=Hv42{`pD$!oy7*!=u1@GY!- zJHhF!|N0ZS^5-)CJK+0S{T~N=zL)+3p&RQLk}n1yWAmrQU_M{;gCAh!UkhH&?EPVI zE%Sd4+#4(9zXHC6+4KA0!>s;H6`0R4eGCV0am)CH;9h2LHQ-}I4g3H6ObfV=^?&QZ zyWf}b?*(VCk-QIV{9Pidk3WM)Hc9^vC_bAX44DW2D(QbQ*w6G^0xo3h*=68Au=ccu z;y)teZvx-S^zkb&*Vk@hpA7#RcnQ1T^$vI+Yd>FsY2Rf!sC^E;4EFK3fL49$fdi)=t zo6>&?cp+f4E@>QMD?8jHvWDU z@i6dAw!WSTzKzMN0`H*y)}i$WmxJwWd=7z6G5fm-Y-8)`d%+DK$ozbs1!n#C5@#vSk70N34FvfRowt#zJrl+87;F-*w>O%)e(8^aFjw!=K8(3jS+H zNPRv4=If{JUX9`KA9TFn=Fm3V1)pFgk=if)86H*Mr-b zy#&Bj zk>NvN{yxYpVE%iHpMrO=`(wWYpPVk^zXon$wY1*3Vh(O z0thhCNb{or^qP8?K!--Ac8_LhpZ9v`1_z+E@U@bkfi zm;=&5@ms*jWs=u|x3T_a6PV9e`^cZ!Bi)PGF+|3H1^m$ylD`03nLd}o-i*KLN9}6> z`q~~gf4&HOi0Qi=T*U0p3AX)7%D)M$u>9T&E@iwEyo;s(CvZ|&#y%opL**>>`kKQc9{|5Xx8?O$6kFoyp zBQSrzq-wW=!O7gSdk*t4w z9ek9H&mVw~vHswDa20FcX-gsReJO7;IKbjB0Q29YxWT1oWcX{qc2<8|!0Eq~{*Qs< zS^oYAE>fhvKL8tl!;tFtD{u?5{|oBSA8eNL^1$2J_*@BIi!qxH(zgp-_lV?czoWW%WnaA3+qo8fcLTWnj2is=5rgs zU$Fe#3+}=kjt(l%GvMQ$l0N_sXZDk{9Q_HKzvO~TpOWG0!ADv7uLILj5J&R?Rk;n^ z@)ymG(%TNs@yPQ2p8Ri@{%?UNGW$6J-t(^XPrMxVz~*aNU_aCEH1J;5zAp!NvGsI2 z_%!-(Iw(Is0`GZHav%86PRTEU556Y(LomOe_XT+OtKoz3T)!H4Kagg7XFH-e8{BI9obA08}u8--`(-wUo}_4_7xH?!}r!Tf!z*elR~ zT`T2X1b!eWc@DU+Nb(in{szgbz(-krehfau=2s7ck57`}e*-?i^m`b5iuL#3g8gj# zx53tJumL(qA2Yx?%s%SDyP1Ak!TfpYTJZ8iGX77%wM_qyfxlqw@kMayOd0-7@Tctl z)MwxrWyumqwzK&`5d7}Hr2p;UdiK2FF>nL(-w%!%EA8Vb z_$2FJPk|4x{&8pn{xSfYZ(ai4$n;kZ-teJJ-wiJRLh?1>eQdnF9~_t^{da>4XGkX7 zu(SU2BzWy%=|9MYKhm;F=06*}jrFH9!9A>gyx{F@ez^wxAj|)c!Cw?h`P;yoS$lXE zyn}Xfz(Mx&4!G;I4F7Mi@i$Uwd`N4Ip6}#=s|scKx!~>09+rW-So>%PH&|qP8z?@z zANo`94q7ANp#1y}e4N?eU%|bsKmQnP{LNX)-#6e*EWQUSu(g^eGl(Lc%cUyL#Z{>NBjgR%<<1GFf@Ol=06L=e&Pd@@~_(bM^FL)2r z*PCE^M}!WlpD)1O(7C}eUKIZc$s@oghDgo9BD+NZy6u{WnRT53Zjnc?EdK=aR1j z^WWc0z}U*4FKmW?FPlF+2QFpx{|0#ES}E^S@Cnu*TbptJi-os=tFM&d3&8cCO0EUB zd?k4$c;hO`H-YW!eTY8r`fH{CYhdMD$sdA^ze`Q+>kN40v(kTT3+CsnK4*d3ilu)Y zIE&@~T5uJskGsJQuxUC-|GxsyWcNRQ1EzbBhW}r{yUQgX1NXE02Z=uP&uo0m2j7K0 z--v%1*vj(L1YW;T`dVHkOCdP$w)9^N zu44Xvuz$4d|2Bemu>Srb@X4t%{%^tbn_W7nK3@j=nLa)T)11Zdw_xmzXZAA+T<{C& zUj+X8D#=%X_gyM^4TWd=y$2kRK8X%W{~53iZQkI&fDa9m89O0bQ!H$T|kApLIuS2F$I1wO*wSNt`2y+ek75uDBDH}8Xc znf|{4=dk)4+>YlZ|B~_T;GVxqE(OHjo%8_WN2)CK>03^`zaf1(H+6PEc~1nyz?Q(D0Btbe_Y z!Vi$o8+yR|XUp_=fzz4&{29!Duk;r91k?AI;E~M!2cT`lhNQfS;ProyTm?RPflS{E z-pA@Y4DS10hTjP8W$FEr;xqrf)gN=O@NFM$sw$jh)|2FWWOuv2LeHarA`OkpsiX^`Z9=Tfb_u!mZ znciT`C;0D0$AbC#tq`2g>~|@63wwWf1-SI*QvP+|oftFepz_`a?q>D7i~N~Az6L)1 zh7A8tZ~$$b4vHVwf&Q^X@>p=PUGgk&>En{?z}Yh;w}C%;S8_M_@VAoh1D7*?98AyS zV-SR%ul^RC&C-7be2|s*eQ-;X)MqT_LV-C_{)PJ7h+L>Vg#BmN!WmccT;9pIy7(*H&9A!gr4zz13WzXTVs_0a{GJ9aOS@pHhB9g;i;?5U94 z4Bj|U@-^W7tUhlCD^{7mUxVwPli^%`*NU!2EvFKgb_>q=W3u zyaw$9f6uENOz}s6Z(#E;JGd`Z1Q+4wfpb`Y)B@)7fprwVUxwcTcChy`o&xV@^W(R` zhuQq$Gw|+bWPIz@=nq(bG6B4v*C%)@TOWJDyP3Y%f%mcg_8xE+n;$$4uD8kbUIicV zNInK$hc-+H>C3tn?QN6fiC{lVZ!TC_CjFOz9c(;a0}inGJz%cC$HDyl?LUFHv-!)v zz}tpP`%k_G^9!cmN#HPhe{UgpBx|1@aQC+|e`~-6QzUN$@BLEpHt?2u$-BYEUP5Fq ze*vem@_i28*et^j#MpT7?~*SDw=9x89n9}1l#@SffDY1kJNU@UlJ5bZWcB$3c!y8w zV;}j?l;Ph4zst%Ke=YnUkp7wAcs3t!fQwlBst30)z8YNGAmeWV`>|%GgYvrr9GEEi z_u!LkJURm2HB0(`4L-3^^3e6TU&ZWcJb24g=|2;Eki}m@{;a{(Hgv_l|FX!z@4l1Rp;t!^d5R{IdRQEcnN)zbplF`>p{WX8QDi18hCC z4&2Xv|8XaHI}86yaG2@iIdD8%FTDlsX8qGC@F9$8bWr_dT@U@7l3WH(|5$PZnE&2A z06xspyBXY#H6$G*?|v}vUw4A}`27;t&+fl{1TJ9h@eFvw5+P2=8+-%g-XnP|_z+wF z&Hy{u__zdog7r@~lRwi}A9#mX%KII7 zu7J46@+eth5k}wsvt0n~WPu3h+lJwXHorK}wi~(F3?vlBJ{E!8{PXNh64@?;Ht*0j zvZ2h1ZBnt5kJF1ClUkjPp^!5V6yl_BgXL}Nz0@Rh5ftoMmma z$y1HrwaQzGeKp$LtL>36*p&)9w4AkPkk}*ydu2sJK~mX*66aiR8#cTMdl$506Er)v zA2W6=i`o+-vfGD|Ex*6U8(!e;3RktPo{vq$Wa>)_ofXxK%EhiP!ANS&q@1d@{K?pc z%qvTcOqBXUsGT-!%Oz##8bcD*UTnd(ippArU0IONVr`$aT3;*naSL+|QY~WpA?#sd z?DG{#opvyBcF<;EP1r*XTWqx=dl6qzmX1J;+tnttib^V5#d1TMs;hO@K-Y7E-m7Xm z+Gszw$WC-pCA3dfEq3~n1@Zf9gI(Bls@Q`azObupiMD&1*aRoCtDPZ$*@;$c?4VnT z{fKCzDqhgW_IB(jCKJJSXr4K)4!_*x1v!SEu$@(Hdlj}uYxnrvC=|(x6dIe(gqmunXWSYW=*nk!A(r!*ZyN;1ouyi%3If z)a4BL+9D3RF;ml=@1nh|glc7OQSaCsE(|Lb9+7yIe_3O+A(fN%>oHV^SK4%<*CyJ?yd+N!8E|ZPHeT zJ}wX?#%Q;?Z*@qj-H7N7V~09w8hSSskqmRgzFT7dGbeTybJ9kLQb~~lx;&B0Vay79 zL%bNlCTBQM0&{N0mSS#2jaBOdyMznL($$X4n zHrV9D7IGeM0J{wu@pNU7s+<*zoB`TpG~%iC@+;A`;&z`A!`%_YmZ#w=uQym7ko|wi zXofJZP%RC)kr=uu{=k^RjZyS>Vy+Pkt&%;4>?2*+>=2u;LM5`#Y7aTx7`J`s3!Lo% zuk=7PU#QaC>~gP$Hlwnm&z7P)G101PXj4PoTN=0DkFFD)Rk$(~Zm(^Rjt3o5zphWq zD!sI=s-Z32uLO;|#)}`!8}8V?)vpb%$Xd`LIa?Cb5T|uwt6r$CL$zu~b+FI%q?auu9jRC1H$S*;G z!!!kID{*16>6euwti~O^v#c=P>aLQYo6k5zNE)m3R!lo+8Z{DaWT8%9*xlj``&u!L ziiDwTXcHW*&x&~X^U;G>i5d8upsTqRrc@g}6PMz#EiOh~eHXom1g!?OK^#?yxs0bB z6F+TRUn7qQBsw+LqeleLR0X@_VLwt98j^VTFN^~n5jHVpfoLMH4>MA!$S>x-w4|8r z3i;falt-fI_5sKhc%b#bjp*`mhqQQzlab%0mr^ z=1AE2QEGyUOInY1!IDfb6aWO&hQ<#4e?nCP*33x>!_t(angP0g-HC;KlNj zW;_w6a|LlPEWtwP5ko;);Y;%J&R-vF9>YYyBC!57=Fxc4Zd4$3_F`#y&g@UK5-gC! zBFYFaEKe-7&t7DU@VK{tkiw>n7{Xnz6l$Z9q@f^f*@^KBtAmn8K7pbosp#6YHIClm zg_|d81p&?Jrhs0QZ(x6I++JyLrmgp_Y2Zyq!BkPZ;da8ldUklqhnri?-Nq z#`eKR;V_jZV=JQ#*;m*4*bGqAXk$mS6E`se*h|@nfl^cB7VDxV+OG0ZJx`?I;?~bO z<(Bq^1w%xr6Ju5DHEDYWHT_Wt>Ziv8oR}R<_SJ(!W5kX9i{DBrZV_uSf>G@h& zut|(eXN}Qfcir=jsS){SbvVpj%(F_pes*JU3GStxr~6xyZ$F>2-#=HoUsv4G1rsi5 zX_KaM)~@l=BS^CV)EunGh5gvEULkXiWJ{k#{LeIR1jb~6SIEMe;z}X4#*5C=BfC^u z4Ymigt;Mk}kn?e;6AhfKSndeA*Nzt!1#W7L!_JBYwM!!Mn_*wn-Qix7Yzr97 z=)NsFc_*zWiyP6su^6~7XAB9&9pQH897sH;`=u;lIpWcK06*@+w3oNzHW}SWW5P&> zG`qrh&RQcHmOf}`Q(0^uj-9Qs{kPE^^a(>1-TlJE603-_yY z@?1m3%$Dv1N8Q!IyyCoLCv_d7H-}A14F{afPTc!kg=w6@SuUu$=nii&#<9*wBnX7b zY6}ulXT$@E(2YA$9NNkqElIAB#0pDaUE!8j2ktO>o9V%a{;0$6uSUtR5QXWrRmjGt zRbAXakMNd891RP)RL4nV}hmbB@dB_j;n6K0=V$u$jJbM?NA%Z!2`i zRd3g5g3|KNUdiae(SEd>2Go3HXrzbscA0l|wHLirs3kf#et%`SwzHj9u+833MO!7t z%^F|VY+qP*oO)+Pxpvm#wr!{tH-^r6+$3&^YxW!|$dbHE&Np;uW(4bsvZ1Jn6;00h z#ELraAeL`V8rUQ9wJD%?72W-3kF@l9k6Pzo)YWg!3frXqLo-Run$8*zJib+Ic0>8q zr?Pb4HA=T=53DMq3WOxZoujBlhSpJ@Gp(a18%?bpT{PjRrDmjvk(t%mH`m1S&ld^> zT<$3Iqlsp5SxsJk;kgTVnnY2reX;(_!NYRIbg{DYZ%rL(yidnZB0~o5AX2(@4ihb9*hB_ zu(;{o84R%Hg5OU=t^2GYQ0pnR0aq*%Bl+~v&2`pURU&3|9hhK5^??m)!!#Xe=67i$~54D91JP&;Rsk$$4*Jg`A~9iDZ!_^kD()aH`Bspp%J=np-p?BTQS zouQyEk0;Wz(la*k_Cq8K$T=+O2ObJ*YU&UVGqGy&2cm19)P>W!J`d!uB~k)+U^ zg6+{=J_bPjZYN$OiJAw{bPbxJTF@7NvYL#MoF-X(-i-Xv!gZB5@{nCK6T31S8Ce-< z$DG$$*5$_ILfoo3Xa0O{1NUCV+ZDvKxzc%Wa7W6Du&7$f-47Xro|?A8@lsi_{^jxI z1fmRmSfk$;!VRD3c|@e?(MS-9t4m(owz7@x;;{S1s84j8XmIBm1lR6d%&9RRte(@} z5fn3KJc`8oVv2jEJJ8`=6~b+gsHdSz@(Q?FMm;Wyu$Y!u&8Af4E)9r5qN`lxD%16F+pcV2latO&+u2UrS$Q+-(JRDe zHZ1r7Be7utV#9(x8(v|Lx-F2G^kVt zKMUOtY75*~v!0rG1j&V`HKtdKUaUr`L>V(iQR`4jagZ7S6*dytJkBB+x(69apLGo! z7M`w7%eWN}bbYlwK<<{mwNPLa+BUC*Xy8Cz^?OuU#>uFnrt|>`nw-?v#(Nc_7Ucnp zHbwCzERvEX6w3meW;)}+D&SsL3Zs?EgJ=T2jjRYHjzKVI1z4!pGD8>(ksSmR#Hzr$ z=@9dY-FvoSDi)&OITuTu3z7;~kwPb2@*HWK=C82Czq9FXh{jehP$#u(Z0{i?AK4fW z0D*3wi7TYCrY=;DI9VYR50cP_5EOL7LBf^eo5P;SV4!CDGIWAocz^eHIRdJ}AGerK zo9+nsiX}^U_;w+3)o^2(6%N;FS+)`A{V;iUWa;;4ARI$@E=N z_GG!e4bLEe46UuFPZZn%K17CCI-84$WHi-c5_4$=MZjE_DYU$q!GjVT5Y-&fM3qtQ z&OU%YlLl`lAkAr7Z0H<6%y~`jd;!h^MI1Q7c*I|zYVy<2FoA+se|mp!LP0;|hZ4R= z&mQruQjxJc{*4$J92T&SfN_sj7q>`by1cFt0n4H-N0!%fVS`F_vAsYV0qQ%LNb))8 za5C|0F5Funb1%^RV6Vc!5=+~k;i9XoOuw@NR%W*YsAjf+@~Ar-qHPtbfHU^s)5zI8 znlb5QKc|(%!NXbZqfKx~Wb9;z$SFc4$XXV5LV)*k8?p=$RSTdMRv9=p?7xotALpK~@UrBm4raLkQR>k~>Xgk)mbDZn-~#h@P&N z7dH?F3fJCQOxNaKDN^0v1TG-F37jGXjt~N~mtcEmmj(}mR!HHO;xd+0xJ-P&%2Ic6 z-UhX3p{Ep+6f<(l1O&xE@Fl8pDc7ECmgmq*#eRi3d4VjrGz?e<`@af0)n^J!m?Qg^ zDp0W1bNHE{p=!X_X9F2vx`JWZlAu>&3xm2_Y`2ItW6s+1Xl8DmbtCNt;qMK= z(G!TnYMkM62+FWDE3;;3Da@B)O{_XVlC@te7WPme9%n;ShA+N;e!JFKm_G^4z{J7n z?NxGiEAryh^42ThD5J`^S1a19fv{v)^P}f~?JpBfB94^FELG}QWIA8M$q7AeKG0Vf z=lmT!0FSGXm=ZsnnNZw9Z8V-lhU9MtARu?BZVPqX;bS?#G&Myrz}2WuidcY7@)b=U zq{xf`9mm^qKJcj-gmqiCW0X)M0OpAh=J5v}UH}6(p(+;+Ft8sK%Rolf1Pp2@31TdR z$sS*AGIBQ(oETx zT;;q`oRO&xIQwDc-^sk^-Jh`diJPrLqgiRmXb#mM$uG+@R_Fz0%j{-JSH^ETAyI+F z6OxxMSkWOW92ghR08d5DO}x&P%*unr)Vns#PO8}sZZ}M?2VKC-IC8 zYmQLKwFC#AJpMTO8}QAZo&&HG|BGo&rKXNe7R3aLjXFm#eHc2j28xx_oa=^3$wvmG zcfNd(&E;Zt)$A_L!&W9Ti#+c*l)Yz1hp)4?{@%6ntC;aoAAi03%N6^H(a_(Pr@oVUi=d+kJ#l6>-bVMATGf zN<^B`pmUBVl7bAUo1KJ`fb~ANY4EC6S$wR zRA4B0OSdoxgvndt6~|y2IY-lr#g88Pc$*Wx{1u#!uim}saNqA5Ox<>=GWiYZ$bz2M zX_nvakc@-rrV<%$XVcJ2t;!{@1sy%|9IE2LW80@uId0;RQ4$Cd@UJ*;(?ja;H^fRQ z9ejz}C8@R%9^`W~tTln}O`T%ryBqPa_-z3y1gR`5UIyso%t`>^b=XlrnJLonofOcdR0GdomlRy9~*a6c+@5sv)??>yy8Q;Yl?yAx9JrD<& z7)lJu9zsp+XxvOeML+@Wxgn$Q3;X;@A#Y=tr^DKI0r*hnHWpA4QKe2Rj?&2hX%FIn zjTK0a47BF;=x~J`K_F#Im!=ZJ`<;V~XNXb}r_NI1k7xyeQ_Tgyq+YNdtl?BxQ{Ox4 z>&m*CUrcfU*{p3P|FV;6oY|>XorlgF=43| z#I_zhp+tX-+!7t1g%jy2N;08EWg{o3gqF(CPG7L98}w|Q8*B~v1z5CTvc6h~*4kM3 ze3G(BFYgENik_v_5_21eS7|a3jkS`Dhs@dq2avE~ZBGP<2+W=e&83^<>FH7w_us54 zL$x9?Fvm<`48_brr$v59Z3dwP;R_Nw5hD1D6Y1c=L?jiETIU4u-}OnG9^Xd=r;+io6BEhlG(9_ zbl>k8c03F6On7G?aD0Afd$UVbGg^&DtgNB@I=&5qU!xR+el_^DHMZQlt| zsq1S7k7Z0Fi6mz%r@URzXi%SFOvz12YGWLXGFxhol6_8{#P?_msgs!f?s#u75k~+o z325;WVW^qw##>bvU*93l9yF*l(exW+&$_#^&4Ccp!-G30>CRZuM)*^8wMx*%g9pb?ln>paH*JfGb-B)bFrwLNGlSF5s+pu8 zliv^~m7}ql?PMO^SM3D~Z_#ZmjCjl81#JxGV}hVGm0T)sChwOly~!`Mw0ycXC90mg zuXrS+gNDJP;&Y8_iN+*Uw12r=Kdo3h$&dJ{KJ9T7e`Z<{_R9W4?9}xhDrHW~ga?Ni z3O#igaD$>iGIdZw!^O09myZqkg5qvwB)tgIB4^HX)g*CUO3Oxpu*>dna|I2TULSwG zpx#>T-#W<>zBa8*<&tx*y-6sB0O5M@d}N=}V~q6WQRS@seD*ZTq&{t~*1l1}8hTja zw(C2`%mX`@ba`I~*pR5U&!kqEW*8)!8Du_)6N?aN+!|4*Bn-~S3%r!PXFwdkPEMGb zKf%FZXAzz?bo)S#6PcTq8$P8`9C$2SyhcFE(wTi~<2AsD<=e^e^nDW`#5R?mY4XpE zDGtb%nqKEOSCwM%PCN@CW5PTxgA%EDO}1IU*uj~7>Z>E#jo}$*0i9vXc(G6o2Mmb6z{}j;$pj5r~+NYv`^;sh~P1tHI*b138<|+ zT8ky$>o{ddqFRI6tI)^VyhWTP*>tUYi$+*X$Q*5lQPsAyJ zR_K71wjxbNG}ghp8v3gH7HKxm8j+aL*50!l8<3JM7^wwHj^V*kZ#{RV^m)2vbv|IW z74Tj(de?Ywu%K2M44H_SBR9}8s>E4CBd_O|z;IAFIQ2CY5$Ps1iyRJlir&L?HayX0 zO*m8vnCeiex;>xIK-&O%B`wE$gO!nvKSgNgKs2Q`**4VPOO10yPzviwnmwlp#WYKM zcsO$t96$`#+fX6etC#&e(WIZusGuYa?V7>_04)ge@arL_rcy4lC49D$L2}p#2&n-@ zDtYZW7(W=SvzfX0@Ocfmq8bmjO~`;UuBFmcI7lv8#}YSlGV3+`;#DfY#=Jx;E0H;S zuL>xcD!)ifEpqoMT*+BW>bCQ&Tib%3D(~=3ai6+Kk^X+&B8;ARSv&nJZAlCzf6(0P zbxTR5EVZb_==R~`y{a8v*|V|{5(KiFe+8V%*akNgg% z7B>aA;}-*k6BFdIW=zI=ng(ZAo6F_RE!|4Y9i^5(xxBrNoyN34Yn%m0q=Isu-NveD zO{-{yYl-t1hV=qHSS4TMzGUgY(RKm$jbk*A7f&1jW3{6UL(am?56FpC41^S6f&*Ct z!fi-Cplz9L4owL*w5((vVx4qqTrBEb-(@G61ncPuD_nhDo+Zjd_&Qy#qaS_)*4feN z%Z2c&(5nol+STvX;sR{CZtRD^hQv1z=kTd|-LU-*fK?|0R~tMAS`Yj2eF7s)QYG1( zH8P;zYF$;5;zgXTPyEFC#A%k z@fU;PM1h6+h-JsVwv^l+$J}oUd>L5|sKG?r_Ot|}WzueL za&0&V_W-du6($N}kAl*G9k2?i!RRly@3Yh3)9^$}=n>idep4O3oRWDDsw{S&N@Xh= z4rl_4Uk8vq7b4bzt7LooP%cD1zPg3aG%y?7=k24_1|;}VOlCSqd`5lKPHSFSh26Si z^btwxX&wZd-LXDMKvty{1!C3x61Y$_h}d2g?&Zr6kU&93?K+ADZ&?>kAGzNbztqsK2zLnLJZL?e;>HHHV21I25CjrDF1WIUuXK=HtsblrL()-s@q z>!O_B$8)K!E&A0!)FD5X4dRx9r8MG z(J+@sqTPzWJF8=}JH$M^!Sb6M&^e5?4Yl$+`b>`pIUUyCMCZwt8Pw(Uu^xejwnUYspZwy>F@l@9`I@pj3xfWws;Q*4SEvkF#d zM9qg!CSy2QZ#UiKW9o}Y37I_z1uT|rfpn0!ug}lH6?`5Q+M+W{b%);|epXf&j)^ey zYCY{(! zmHJts1(r;6s8wd4Y2QV1eQF*1Cy(}gg+hCfQXoISrXX2d&#Mgmq0fi};^5Vc4Zncg zMC&l0$~H#AYOx+qNR$FdPZH{CYUG1sxGHZqCu`_o=V){zYHCr~Ma%Hl*xOM}F}+MJ zNHkng8o!kjCzPRfqCG)T`$pdibXJL3c-lDRfh_U9{H zWd2m>OQv@6V>s=(0I$Quen;je*n523#k{mOg z#|!zz0&6B;VMjqY5IA?EK}VlCMS!=HUJ?eLCBa(5jv!PeCnw2V zURWJPN9}mRWpeHtpr$1rOL*58IUa5y`(W^Lgp0x@WQ)Rq8n=!VV1G$rXu0PfC>(vx z`T~e>0e;4j9A00i&qW2NR&wg~Y>$4`192*{6@*IA(w?YWI@;Ikv`*A!Ce}D88}a_( z$u|B36yj*xazlSF@(>^Z=&#bwj@eu-{vl7;%06bXkZ9oeRICs&OW$-ozeOXE#;LS( z@~bsK)j6K2fY>9i0p6eqVf7r@I5QFQcwsx6dEeTNw5Bb(Z2CNK+a{Wh~>SllVvYC{I5vg4J*8xJ}7N?GE~b6@8U1WZ-M{8Y$%AVGt1;*zzN$bJvyErXE;Xsyy5 za5iDz4aC(`zMn9dO^zhPeN!dhm1k+<`KxAAwgx{ve)X(EJFHGL94s-(-p3yyyHmeG zgl$s(M0H47zv{0kY^=sW?Q`mbFhTh1{Hh2b=@;6{9{Vhy9|9H1Oiv2pVwnKDB_PFg zyqKIty;LEZXcVNKk5OSpcT!z#hUt4w()J-xdH*T(;y?n`!hbrS)!@TBM<4ulM zuSF9o2&QMt6}%nEuY#>o#KE<4bbWYxlzV^sX6K7)yJ&fiq|dK=SHC!!CG|)Of4N0AR^~5Kn^WB*F8uloPDJl&d9F1lKeKwb|ttwXK zQ(3kzwX>8MqZ{S^>G4g2i@wp}<1t7H<9FZEUBRm+Xo!6rb&K8nmbPyii$(6%ZyLcI zt4#=;^DBJ<_dt!L2mVkCe37w7U!D3h9;DT{Rr<7scgk; z7JnJ_soiwd>wL#U1$V4;1;B`~o?D|V%2CUeORs^&#X*gK@LBCW@Ygr7TKSq`6|9AW z2b|}u;m4l9;}aE!ZYN!5OZ+v~g|&;v96TIw2;Gzt2Tu0XqooLEDxnbW{)V8c?T1H5 z&Ob*!ohG;Xkn$+%nkvAtyS^4oO8X=qPo!goC!iy;UCn(sQlREl7BgyI~e!4A~<5B_<(9j3lwDVLmzIGic zReNL0WM(sk`xWtVGgUeHziX9|6X8J0us152WHBA+r&p1IJ$PMhW}%+0;SvJ|2+v$%;C1u7JQ z1=~BZUaThF5Xo9Alwzk512ow$nYtZ#rC6qUYssYvCoW1ofZE|%<=gxN8%P0qa(mOH zZ=m1@N-6O6F1UnuOI9`#F$+FL|>jPsheV1ZgxC zLgE`B2laQ`vPsfIPD}%9L5|RmvhctlP$75@mREnS5O;{Yyakdlj_>cToW9m$w`?}` ztz@P#(ll5P;*YB4%Upkah6i%BzJYZB4YoKUBB9?KaJxtoIO;0=1(u1A)jbg`wyAuF z#~|jbsbG~j!UrYl?^ur?+!gi()c6LO%I7Z{MBl5RGG9La6q_1982n5OPMR#S$gEgP68*}evZkYydWuls`g^RWAQyR^}K8MkBdMk0Zl1!B4 zg333tcyJ&f2J*5#{e7zB1#3UDGJY`Vh$31D)ObX`z|3hN0@(iJ@TR+?`v*9}Y=@5% zK{BSi`a+9!l-S>(9@2&h3&RXfgzeJ^6}SDiNrRcf2L#0pBBCN~gDm;R-F1W+#1$K% z+v(LJz8qD6(};86Y-_W|qIpwtdn7H<_Zw`Qs3_brFJnBISkJ7?Pkr9;ew|Wc3WC40 zilN&AKuX|<=qL{Xs2?F#k&qX|EkHSXK3#3Kh1GEtvcGEzf3FDGIX-6H4^8r5#4Po4 z24f3Bg~}0n!pvs}R+KE3O@RGkf~*0QubP#SNB6(5;dfmU&@t{;C2z$4QX(WGqEP;_ zas<##z+@Jrr}%J#^C`4nesT%~OHX$L-n6@ZL+E`e$oC2H{(Vpw{R;XW<$MPV*nZd} zcaXjz<}UFOi1AD5gccu^au!I_>RVyv`~vh2(2BUSPPB7Gdyo_kRmn(F1pM8Oyp5;i z42!*;z&eIEzHS>BdgT6bq!R)kh&6+?5B@S$^s|sRo8s(DK8G^8hc@Ww%Z#5eh2`g^ z{RS5Nq?>I<_r%41&q_k>Q3D>`qj-Kjh#4V%+EUJAZHt|Bdlq`JI1%_WM{%IQpVQIk zQl8NNm3zO7KY6z0-{UX7H~R1L2Y!}u{7IZD|6aTqjs6yg^n19lhyS<_o(WMh&-Y*d PIvTzEDK6T-GT;9L0{epu diff --git a/include/dw_dmac.h b/include/dw_dmac.h index 6ff772d..64068c4 100755 --- a/include/dw_dmac.h +++ b/include/dw_dmac.h @@ -102,6 +102,7 @@ typedef enum { #define DMA_REG_Cfg 0x398 #define DMA_REG_ChEn 0x3a0 +#define DMA_MAX_TRANSPORT_SIZE(ch) ((ch == 0) ? 0x7ff : 0x1f) //typedef struct { // __IOM uint32_t SAR; /* offset: 0x00 (R/W) Channel Source Address Register */ // __IOM uint32_t DAR; /* offset: 0x04 (R/W) Channel Destination Address Register */ diff --git a/include/spif.h b/include/spif.h index f9f4313..0077f3b 100755 --- a/include/spif.h +++ b/include/spif.h @@ -52,6 +52,11 @@ extern "C" { #define XFRD_FCMD_READ 0x801000B #define XFRD_FCMD_READ_DUAL 0x801003B #define XFRD_FCMD_READ_QUAD 0x801006B +#define XFRD_FCMD_WREN 0x6000001 +#define XFRD_FCMD_WRDI 0x4000001 //flash write disable +#define XFRD_FCMD_WRST 0x1008001 + + #define FCMD_RESET 0x99 //reset @@ -81,6 +86,45 @@ extern "C" { #define FCMD_READQIO 0xeB //quad I/O fast read #define FCMD_READQIOW 0xe7 //quad I/O fast read word +#define FCMD_CMD_EXCUTE 0x01 +#define FCMD_SRP_REG 0x80 +#define FCMD_DATAPRO_AREA_NONE 0x00 +#define FCMD_DATAPRO_AREA_504 0x04 +#define FCMD_DATAPRO_AREA_496 0x08 +#define FCMD_DATAPRO_AREA_480 0x0c +#define FCMD_DATAPRO_AREA_448 0x10 +#define FCMD_DATAPRO_AREA_384 0x14 +#define FCMD_DATAPRO_AREA_256 0x18 +#define FCMD_DATAPRO_AREA_512 0x1c + +#define FCMD_DATAPRO_NONE_BIT 0x00 +#define FCMD_DATAPRO_504_BIT 0x04 +#define FCMD_DATAPRO_496_BIT 0x08 +#define FCMD_DATAPRO_480_BIT 0x0c +#define FCMD_DATAPRO_448_BIT 0x10 +#define FCMD_DATAPRO_384_BIT 0x14 +#define FCMD_DATAPRO_256_BIT 0x18 +#define FCMD_DATAPRO_512_BIT 0x1c + + +#define FLASH_STATUS_REGISTER_LEN 1 + +#define XFRD_FCMD_WREN 0x6000001 +#define XFRD_FCMD_WRST 0x1008001 + +#define FLASH_WP_HIGH_LEVEL (AP_SPIF->config &= ~(1<<14)) +#define FLASH_WP_LOW_LEVEL (AP_SPIF->config |= (1<<14)) +#define FLASH_WP_LEVEL_GET (0x4000-(AP_SPIF->config & (1<<14))) + +extern uint8_t spif_flash_status_reg_1(void); +extern void spif_wrdata(uint8_t* data, uint8_t len); + +__attribute__((section(".__sram.code"))) int hal_flash_rd_status_reg(uint8* buf,bool low_8bit); +__attribute__((section(".__sram.code"))) int hal_flash_wr_status_reg(uint8* buf,int len); + +__attribute__((section(".__sram.code"))) int hal_flash_switch_hardware_protect_mode(void); +__attribute__((section(".__sram.code"))) int hal_flash_switch_hardware_unprotect_mode(void); + #ifdef __cplusplus } #endif diff --git a/misc/rom_sym_def.h b/misc/rom_sym_def.h index 7ed7555..2cc7539 100755 --- a/misc/rom_sym_def.h +++ b/misc/rom_sym_def.h @@ -4,6 +4,8 @@ #define __ROM_SYM_H__ #ifdef USE_ROMSYM_ALIAS +#define g_system_reset_cause _symrom_g_system_reset_cause +#define SystemResetCause _symrom_SystemResetCause #define WaitMs _symrom_WaitMs #define WaitRTCCount _symrom_WaitRTCCount #define WaitUs _symrom_WaitUs @@ -569,7 +571,7 @@ #define LL_SetPeriodicAdvEnable _symrom_LL_SetPeriodicAdvEnable #define LL_SetPeriodicAdvParameter _symrom_LL_SetPeriodicAdvParameter #define LL_SetPhyMode _symrom_LL_SetPhyMode -#define LL_SetRandomAddress _symrom_LL_SetRandomAddress +//#define LL_SetRandomAddress _symrom_LL_SetRandomAddress #define LL_SetResolvablePrivateAddressTimeout _symrom_LL_SetResolvablePrivateAddressTimeout #define LL_SetScanControl _symrom_LL_SetScanControl #define LL_SetScanParam _symrom_LL_SetScanParam @@ -909,6 +911,14 @@ #define rom_hal_uart_send_buff _symrom_hal_uart_send_buff #define rom_hal_uart_tx _symrom_hal_uart_tx #define move_to_slave_function0 _symrom_move_to_slave_function0 +#define ll_scheduler0 _symrom_ll_scheduler0 +#define g_llAdvMode _symrom_g_llAdvMode +#define LL_AdvSetTerminatedCback _symrom_LL_AdvSetTerminatedCback +#define g_timer4_irq_pending_time _symrom_g_timer4_irq_pending_time +#define llSetupNextSlaveEvent0 _symrom_llSetupNextSlaveEvent0 +#define llProcessSlaveControlPacket0 _symrom_llProcessSlaveControlPacket0 +#define llProcessMasterControlPacket0 _symrom_llProcessMasterControlPacket0 +#define LL_slave_conn_event0 _symrom_LL_slave_conn_event0 #endif #endif diff --git a/phy_pmu.c b/phy_pmu.c index 7e9e78f..9ef98f6 100755 --- a/phy_pmu.c +++ b/phy_pmu.c @@ -25,7 +25,7 @@ #include #include - +#include "global_config.h" #define ERR_PMU(errno) (CSI_DRV_ERRNO_PMU_BASE | errno) #define PMU_NULL_PARAM_CHK(para) HANDLE_PARAM_CHK(para, ERR_PMU(DRV_ERROR_PARAMETER)) @@ -43,7 +43,7 @@ static phy_pmu_priv_t pmu_handle[CONFIG_PMU_NUM]; #define CONFIG_CORETIM_REGISTER_NUM_SAVE 2 static uint32_t cortim_regs_saved[CONFIG_CORETIM_REGISTER_NUM_SAVE]; -#define CONFIG_VIC_REGISTER_NUM_SAVE 3 +#define CONFIG_VIC_REGISTER_NUM_SAVE 11 static uint32_t vic_regs_saved[CONFIG_VIC_REGISTER_NUM_SAVE]; #define CONFIG_CPU_REGISTER_NUM_SAVE 28 @@ -55,11 +55,19 @@ uint32_t g_arch_cpu_saved[CONFIG_CPU_REGISTER_NUM_SAVE]; // static void do_prepare_sleep_action(int32_t idx) { + int i = 0; + /* save vic register */ vic_regs_saved[0] = VIC->ISER[0U]; vic_regs_saved[1] = VIC->ISPR[0U]; vic_regs_saved[2] = VIC->IPTR; + /* save irq priority reg */ + for (i = 0;i < 8; i++) + { + vic_regs_saved[3 + i] = VIC->IPR[i]; + } + /* save the coretim register */ cortim_regs_saved[0] = CORET->LOAD; cortim_regs_saved[1] = CORET->CTRL; @@ -67,11 +75,21 @@ static void do_prepare_sleep_action(int32_t idx) static void do_wakeup_sleep_action(int32_t idx) { + int i = 0; + + subWriteReg(&AP_SPIF->config, 14, 14, 1); //enable wp bit(14) + /* resume vic register */ VIC->ISER[0U] = vic_regs_saved[0]; VIC->ISPR[0U] = vic_regs_saved[1]; VIC->IPTR = vic_regs_saved[2]; + /* resume irq priority reg */ + for (i = 0;i < 8; i++) + { + VIC->IPR[i] = vic_regs_saved[3 + i]; + } + /* resume the coretim register */ CORET->LOAD = cortim_regs_saved[0]; CORET->VAL = 0UL; @@ -96,7 +114,10 @@ pmu_handle_t csi_pmu_initialize(int32_t idx, pmu_event_cb_t cb_event) pmu_priv->idx = idx; pmu_priv->cb = cb_event; - JUMP_FUNCTION(WAKEUP_PROCESS) = (uint32_t)arch_do_cpu_resume; + /* + WAKEUP_PROCESS jump func will be registed as arch_do_cpu_resume in enter_sleep_process + */ + //JUMP_FUNCTION(WAKEUP_PROCESS) = (uint32_t)arch_do_cpu_resume; return (pmu_handle_t)pmu_priv; } @@ -178,6 +199,17 @@ int32_t csi_pmu_enter_sleep(pmu_handle_t handle, pmu_mode_e mode) do_prepare_sleep_action(0); if (arch_do_cpu_save() == 0) { + subWriteReg(0x4000f03c, 2, 0, 0); //switch hclk to RC32M + uint32_t rtc_current; + extern uint32 *pGlobal_config; + rtc_current = rtc_get_counter(); + if(((AP_AON->RTCCC0 - rtc_current)>(pGlobal_config[MAX_SLEEP_TIME]>>4)) || + ((AP_AON->RTCCC0 - rtc_current)<(pGlobal_config[MIN_SLEEP_TIME]>>6))) + { + just_enter_sleep(33000); + } + extern int32_t arch_do_cpu_resume(void); + JUMP_FUNCTION(WAKEUP_PROCESS) = (uint32_t)arch_do_cpu_resume; enter_sleep_off_mode(SYSTEM_SLEEP_MODE); } diff --git a/pm.c b/pm.c index f18ab0a..4a0093a 100755 --- a/pm.c +++ b/pm.c @@ -99,7 +99,7 @@ pm_wakeup_by_io_cb g_wakeup_cb = NULL; #define PMU_ADDROFF (0x1F0) #ifndef CONFIG_WDT -#define CONFIG_WDT 0 +#define CONFIG_WDT 1 #endif #if (CONFIG_WDT > 0) @@ -200,7 +200,7 @@ void wdt_wakeup_action() while (delay-- > 0); - AP_WDT->CR = 0x1F; + AP_WDT->CR = 0x1D; csi_wdt_set_timeout(wdt_handle, WDT_TIMEOUT); #endif @@ -437,7 +437,6 @@ void enterSleepProcess1(uint32_t time) // 5. set sleep flag(AON reg & retention SRAM variable) set_sleep_flag(1); - // 6. trigger system sleep csi_pmu_enter_sleep(pmu_handle, PMU_MODE_DORMANT); } @@ -447,7 +446,11 @@ void osal_pwrmgr_powerconserve_dummy(void) //do nothing return; } - +void sram_HardFault_Handler(void) +{ + subWriteReg(&(AP_PCRM->CLKSEL),2,0,SYS_CLK_RC_32M); + drv_reboot(1); +} /****************************************** // SOC interfaces ******************************************/ @@ -469,6 +472,8 @@ int sys_soc_suspend(uint32_t suspend_tick) RHINO_CPU_INTRPT_DISABLE(); irq_flags = psr; + check_hclk_by_rc32k_rtc(); + if (!isSleepAllowInPM()) { RHINO_CPU_INTRPT_ENABLE(); __WFI(); @@ -637,6 +642,282 @@ int sys_soc_suspend(uint32_t suspend_tick) #define BASE_TIME_UNITS (0x3fffff) #endif +#define CRY32_2_CYCLE_16MHZ_CYCLE_MAX (976 + 98) // tracking value range std +/- 20% +#define CRY32_2_CYCLE_16MHZ_CYCLE_MIN (976 - 98) +#define CRY32_2_CYCLE_DELTA_LMT (19) +#define TRACKING_96M_16M_MULTI6_DELTA_LIMIT (10*6) //96M:16M*6 +- 1% +#define DLL_ENABLE_MAX (5) +#define TRACKING_16M_TICK_MAX (3300) +#define TRACKING_MAX_SLEEPTIME (1980000) //MAX sleep time is 60 seconds. + +//volatile uint8_t g_rc32kCalRes = 0xff; +uint32_t g_xtal16M_tmp=0; +uint32_t g_xtal96M_temp=0; +uint32_t DLL_enable_num=1; +uint32_t tracking_16M_num = 0; +extern void Reset_Handler(); +extern int SystemResetCause(void); +extern uint32_t g_system_reset_cause; +void _rom_data_init(void) +{ + //copy rom data section + osal_memcpy(0x1fff0800,0x17c7c,(0x1fff0924-0x1fff0800)); + //clr rom bss section skip g_top_trapstack + osal_memset(0x1fff0924,0,(0x1fff0988-0x1fff0924)); + osal_memset(0x1fff0b8c,0,(0x1fff1a3c-0x1fff0b8c)); +} + +void sram_reset_handler(void) +{ + subWriteReg(&AP_SPIF->config, 14, 14, 1); //enable wp bit(14) + + AP_PCR->CACHE_BYPASS = 1;//disable cache + AP_SPIF->fcmd_wrdata[0] = 0x94; + clk_init(SYS_CLK_RC_32M); + config_reset_handler(1); + + + + g_spif_ref_clk = SYS_CLK_RC_32M; + hal_cache_init(); + hal_flash_write_disable(); + hal_mpu_config(); + + _rom_data_init(); + + + + /* + update reset cause, add 0x80 to mark the reset path from sram_reset_handler + */ + SystemResetCause(); + g_system_reset_cause |=0x80; + + //check just_sleep_reset flg + if((((*(volatile uint32_t*)0x4000f0c4) & 0x0f)>>2)) + g_system_reset_cause |=0x40; + + Reset_Handler(); +} +void just_enter_sleep(uint32 time) +{ + JUMP_FUNCTION(WAKEUP_PROCESS) = (uint32_t)sram_reset_handler; + + /* set sleep flag , rom boot will check the flag and + set reset path from WAKEUP_PROCESS */ + phy_gpioretention_disable(); + set_sleep_flag(1); + + subWriteReg(&(AP_AON->PMCTL2_0),6,6,0x00); //disable software control + // config wakeup timer + uint32_t sleep_tick_now = *(volatile uint32_t *) 0x4000f028; + WaitRTCCount(1); + AP_AON->RTCCC0 = sleep_tick_now + time; + AP_AON->RTCCTL |= BIT(15)|BIT(18)|BIT(20); + + // clear sram retention + // hal_pwrmgr_RAM_retention_clr(); + + /** + config reset casue as RSTC_WARM_NDWC + reset path walkaround dwc + */ + AP_AON->SLEEP_R[0]=4; + + // trigger system sleep + enter_sleep_off_mode(SYSTEM_SLEEP_MODE); +} + + +#define RTC_32KRC_3_CYCLE_LIMIT_LOW (60) //3*30.5 normal pclk +#define RTC_32KRC_3_CYCLE_LIMIT_HIGH (120) //3*30.5 normal pclk + +void check_hclk_by_rc32k_rtc(void) +{ + WaitRTCCount(1); + uint32_t t0 = read_current_fine_time(); + WaitRTCCount(3); + uint32_t t1 = read_current_fine_time(); + if((TIME_DELTA(t1,t0)RTC_32KRC_3_CYCLE_LIMIT_HIGH)) + { + subWriteReg(0x4000f03c, 2, 0, 0); //switch hclk to RC32M + just_enter_sleep(33000); + + } + + +} + + +void check_16MXtal_by_rcTracking(void) +{ + /* + + for fiset wakeupini, not do rcCal, just skip the rcTacking + */ + + if(((*(volatile uint32_t*)0x4000f0c4) & 0x80) == 0) + { + WaitRTCCount(60); + return; + } + + uint32_t tracking_start = rtc_get_counter(); + + uint32_t temp,temp1; + uint32_t temp31,temp32,temp33; + uint32_t temp_min,temp_max; + + // ======== enable tracking 32KHz RC timer with 16MHz crystal clock + temp = *(volatile uint32_t *)0x4000f040; + *(volatile uint32_t *)0x4000f040 = temp | BIT(18); + temp = *(volatile uint32_t *)0x4000f05C; + *(volatile uint32_t *)0x4000f05C = (temp & 0xfffefe00) | 0x0028; + WaitRTCCount(3); + + temp31 = (*(volatile uint32_t *)0x4000f064 & 0x1ffff); + WaitRTCCount(3); + + temp32 = (*(volatile uint32_t *)0x4000f064 & 0x1ffff); + WaitRTCCount(3); + + temp33 = (*(volatile uint32_t *)0x4000f064 & 0x1ffff); + + while(1) + { + temp_min = (temp31 >=temp32) ? (temp32):(temp31); + temp_min = (temp_min >=temp33) ? (temp33):(temp_min); + temp_max = (temp31 >=temp32) ? (temp31):(temp32); + temp_max = (temp_max >=temp33) ? (temp_max):(temp33); + + if( temp31>CRY32_2_CYCLE_16MHZ_CYCLE_MIN && + temp31CRY32_2_CYCLE_16MHZ_CYCLE_MIN && + temp32 CRY32_2_CYCLE_16MHZ_CYCLE_MIN && + temp33 =tracking_start) ? (tracking_end-tracking_start) : (0xffffffff-tracking_start+tracking_end); + if(tracking_16M_tick >= TRACKING_16M_TICK_MAX) + { + uint32_t tracking_sleep_num = (*(volatile uint32_t*)0x4000f0c4 & 0xFF00) >>8; + subWriteReg(0x4000f0c4,15,8,tracking_sleep_num+1); + subWriteReg(0x4000f0c4,3,2,1); + if ((1 << tracking_sleep_num)*33000< TRACKING_MAX_SLEEPTIME) + { + just_enter_sleep((1 << tracking_sleep_num)*33000); + } + else + { + just_enter_sleep(TRACKING_MAX_SLEEPTIME); + } + } + + } + + temp1 = (*(volatile uint32_t *)0x4000f064 & 0x1ffff); + + subWriteReg(0x4000f05C,3,3,0); + + g_xtal16M_tmp = temp1; +} + +void check_96MXtal_by_rcTracking(void) +{ + uint32_t temp,temp1; + //for first wakeupinit + + if(((*(volatile uint32_t*)0x4000f0c4) & 0x80) == 0) + { + //enable DLL + temp = *(volatile uint32_t *)0x4000f044; + *(volatile uint32_t *)0x4000f044 = temp | BIT(7); + WaitRTCCount(3); + return; + } + + DLL_enable_num=0; + + // ======== enable tracking 32KHz RC timer with 16MHz crystal clock + temp = *(volatile uint32_t *)0x4000f040; + *(volatile uint32_t *)0x4000f040 = temp | BIT(18); + + while(1) + { + //enable DLL + temp = *(volatile uint32_t *)0x4000f044; + *(volatile uint32_t *)0x4000f044 = temp | BIT(7); + WaitRTCCount(3); + DLL_enable_num++; + + // //enable digclk 96M + + temp = *(volatile uint32_t *)0x4000f044; + *(volatile uint32_t *)0x4000f044 = temp | BIT(16); + for(uint8 index=0;index<5;index++) + { + temp = *(volatile uint32_t *)0x4000f05C; + *(volatile uint32_t *)0x4000f05C = (temp & 0xfffefe00) | 0x0028 | BIT(16); + WaitRTCCount(3); + temp1 = (*(volatile uint32_t *)0x4000f064 & 0x1ffff); + subWriteReg(0x4000f05C,3,3,0); + if( (g_xtal16M_tmp*6 >=temp1 ? (g_xtal16M_tmp*6 -temp1):(temp1-g_xtal16M_tmp*6))= DLL_ENABLE_MAX) + { + subWriteReg(0x4000f0c4,5,4,1); + just_enter_sleep(60); + } + + //disable DLL + + subWriteReg(0x4000f044,7,7,0); + WaitRTCCount(3); + + //update g_xtal16M_tmp + temp = *(volatile uint32_t *)0x4000f05C; + *(volatile uint32_t *)0x4000f05C = (temp & 0xfffefe00) | 0x0028 ; + WaitRTCCount(3); + g_xtal16M_tmp = (*(volatile uint32_t *)0x4000f064 & 0x1ffff); + + subWriteReg(0x4000f05C,3,3,0); + } + +} + +uint32_t tracking_cnt=0; void wakeup_init1() { uint8_t pktFmt = 1; // packet format 1: BLE 1M uint32_t temp; @@ -647,7 +928,28 @@ void wakeup_init1() { //each rtc count is about 30.5us //after 15count , xtal will be feedout to dll and doubler - WaitRTCCount(pGlobal_config[WAKEUP_DELAY]); + //WaitRTCCount(pGlobal_config[WAKEUP_DELAY]); + if(g_system_clk == SYS_CLK_XTAL_16M) + { + //WaitRTCCount(pGlobal_config[WAKEUP_DELAY]); + WaitRTCCount(10); + check_16MXtal_by_rcTracking(); + } + else + { + uint32_t tracking_c1,tracking_c2; + tracking_c1 = rtc_get_counter(); + WaitRTCCount(30); + subWriteReg(0x4000f0c4,1,0,0); + check_16MXtal_by_rcTracking(); + WaitRTCCount(6); + subWriteReg(0x4000f0c4,1,0,1); + check_96MXtal_by_rcTracking(); + subWriteReg(0x4000f0c4,1,0,2); + tracking_c2 = rtc_get_counter(); + tracking_cnt = (tracking_c2>=tracking_c1) ? (tracking_c2-tracking_c1) : (0xffffffff-tracking_c1+tracking_c2); + pGlobal_config[WAKEUP_ADVANCE] =1500+30*tracking_cnt; + } // ============ config BB Top *(volatile uint32_t *) 0x40030000 = 0x3d068001; // set tx pkt =2 @@ -655,7 +957,7 @@ void wakeup_init1() { *(volatile uint32_t *) 0x400300a4 = 0x140; //[6] for tpm_en clk_init(g_system_clk); - + subWriteReg(0x4000f0c4,1,0,3); hal_wakeup_irq_config(); // ========== init timers @@ -689,6 +991,8 @@ static void hw_spif_cache_config(void) { hal_cache_init(); } +extern void efuse_init(void); + int sys_soc_resume(int pm_state) { uint32_t current_RTC_tick; uint32_t wakeup_time, wakeup_time0, next_time; @@ -698,6 +1002,15 @@ int sys_soc_resume(int pm_state) { if (pm_state == SYS_POWER_STATE_RUN) { return 0; } + + AP_PCR->CACHE_BYPASS = 1;//disable cache + AP_SPIF->fcmd_wrdata[0] = 0x94; + + config_reset_handler(1); + + efuse_init(); + + wdt_wakeup_action(); DBG_GPIO_WRITE(DBGIO_APP_WAKEUP, 1); // restore HW registers @@ -723,14 +1036,14 @@ int sys_soc_resume(int pm_state) { //config the tx2rx timing according to the g_rfPhyPktFmt ll_hw_tx2rx_timing_config(g_rfPhyPktFmt); - if (pGlobal_config[LL_SWITCH] & LL_RC32K_SEL) { - subWriteReg(0x4000f01c, 16, 7, 0x3fb); //software control 32k_clk - subWriteReg(0x4000f01c, 6, 6 , 0x01); //enable software control + // if (pGlobal_config[LL_SWITCH] & LL_RC32K_SEL) { + // subWriteReg(0x4000f01c, 16, 7, 0x3fb); //software control 32k_clk + // subWriteReg(0x4000f01c, 6, 6 , 0x01); //enable software control - } else { - subWriteReg(0x4000f01c, 9, 8, 0x03); //software control 32k_clk - subWriteReg(0x4000f01c, 6, 6, 0x00); //disable software control - } + // } else { + // subWriteReg(0x4000f01c, 9, 8, 0x03); //software control 32k_clk + // subWriteReg(0x4000f01c, 6, 6, 0x00); //disable software control + // } //20181201 by ZQ //restart the TIM2 to align the RTC @@ -858,7 +1171,7 @@ int sys_soc_resume(int pm_state) { ll_debug_output(DEBUG_WAKEUP); - set_sleep_flag(0); +// set_sleep_flag(0); DBG_GPIO_WRITE(DBGIO_APP_WAKEUP, 1); @@ -866,12 +1179,27 @@ int sys_soc_resume(int pm_state) { hal_mpu_config(); //clk_spif_ref_clk(g_spif_ref_clk); - + /* clear tick irq state by reading reg */ + int count; + unsigned int v = *((volatile unsigned int *) (0xE000E010)); + while((v & 0x10000) > 0) + { + v = *((volatile unsigned int *) (0xE000E010)); + count++; + } + #if (CONFIG_LOW_POWER_WAKE_DEBUG == 1) + gpio_write(P25,1); + gpio_write(P25,0); + #endif CPSR_ALLOC(); psr = irq_flags; RHINO_CPU_INTRPT_ENABLE(); - wdt_wakeup_action(); +// wdt_wakeup_action(); + #if(CONFIG_LOW_POWER_WAKE_DEBUG == 1) + gpio_write(P33,1); + gpio_write(P33,0); + #endif //usart_wakeup_action(); pm_after_sleep_action(); diff --git a/reboot.c b/reboot.c index b64b501..207ffc4 100755 --- a/reboot.c +++ b/reboot.c @@ -14,27 +14,49 @@ #include #include #include +#include "jump_function.h" + +#define RST_FROM_ROM_BOOT 0 +#define RST_FROM_APP_RST_HANDLER 1 + extern size_t cpu_intrpt_save(void); +extern void sram_reset_handler(void); -__attribute__((section(".__sram.code"))) void drv_reboot(int cmd) +__attribute__((section(".__sram.code"))) void config_reset_handler(int rstMod) { - csi_irq_save(); + jump_area_init(); + if(rstMod==RST_FROM_ROM_BOOT) + { + set_sleep_flag(0); + } + else + { + JUMP_FUNCTION(WAKEUP_PROCESS) = (uint32_t)sram_reset_handler; + extern void trap_c(uint32_t *regs); + extern void sram_HardFault_Handler(void); + JUMP_FUNCTION(CK802_TRAP_C) = (uint32_t)&sram_HardFault_Handler; //register trap irq handler + set_sleep_flag(1); + } +} - volatile int dly = 100; +__attribute__((section(".__sram.code"))) void drv_reboot(int cmd) +{ + csi_irq_save(); - //cache rst + AP_PCR->CACHE_BYPASS = 1; +// hal_flash_write_disable(); +// AP_SPIF->config = 0; AP_PCR->CACHE_RST = 0; - while (dly--) {}; + // config reset path , from rom or app + config_reset_handler(cmd); + /** + config reset casue as RSTC_WARM_NDWC + reset path walkaround dwc + */ + AP_AON->SLEEP_R[0]=4; - AP_PCR->CACHE_RST = 0x03; - - //cache flush tag - AP_CACHE->CTRL0 = 0x03; - - //cache enable - AP_PCR->CACHE_BYPASS = 1; *(volatile uint32_t *) 0x40000004 = 0x00; diff --git a/system.c b/system.c index 164520e..9dfc8d1 100755 --- a/system.c +++ b/system.c @@ -41,7 +41,7 @@ #endif extern volatile sysclk_t g_system_clk; -int g_spif_ref_clk = SYS_CLK_DLL_64M; +int g_spif_ref_clk = SYS_CLK_RC_32M; extern void trap_c(uint32_t *regs); extern uint32_t g_system_clk; @@ -75,7 +75,7 @@ __attribute__((section(".__sram.code"))) void hal_cache_init(void) hal_clk_gate_enable(MOD_PCLK_CACHE); //cache rst - AP_PCR->CACHE_RST = 0x00; + AP_PCR->CACHE_RST = 0x02; while (dly--) {}; @@ -83,13 +83,16 @@ __attribute__((section(".__sram.code"))) void hal_cache_init(void) AP_PCR->CACHE_RST = 0x03; //cache flush tag - AP_CACHE->CTRL0 = 0x01; + //AP_CACHE->CTRL0 = 0x01; + hal_cache_tag_flush(); //cache enable AP_PCR->CACHE_BYPASS = 0; spif_config(g_spif_ref_clk, 0x1, 0x801003b, 0, 0); + subWriteReg(&AP_SPIF->config, 14, 14, 1); //enable wp bit(14) + AP_SPIF->low_wr_protection = 0; AP_SPIF->up_wr_protection = 0x10; @@ -214,7 +217,7 @@ static void hal_low_power_io_init(void) static void hal_init(void) { hal_low_power_io_init(); - + hal_rtc_clock_config(g_clk32K_config); //hal_pwrmgr_init(); } @@ -233,9 +236,12 @@ __attribute__((section(".__data_copy_first__"))) void check_before_startup() { //check_data = -1; } - void SystemInit(void) { + // /* USE CONFIG_WDT=1 to enable wdt */ + extern void wdt_init(void); + wdt_init(); + subWriteReg(&AP_SPIF->config, 14, 14, 1); //enable wp bit(14) /* Clear active and pending IRQ */ VIC->IABR[0] = 0x0; VIC->ICPR[0] = 0xFFFFFFFF; @@ -243,7 +249,7 @@ void SystemInit(void) __disable_irq(); - g_system_clk = SYS_CLK_DLL_48M; + g_system_clk = SYS_CLK_XTAL_16M; #ifdef CONFIG_USE_XTAL_CLK g_clk32K_config = CLK_32K_XTAL;//CLK_32K_XTAL,CLK_32K_RCOSC @@ -251,11 +257,11 @@ void SystemInit(void) g_clk32K_config = CLK_32K_RCOSC;//CLK_32K_XTAL,CLK_32K_RCOSC #endif - g_spif_ref_clk = SYS_CLK_DLL_64M; + g_spif_ref_clk = SYS_CLK_RC_32M; - hal_rtc_clock_config(g_clk32K_config); - - JUMP_FUNCTION(CK802_TRAP_C) = (uint32_t)&trap_c; //register trap irq handler + + extern void sram_HardFault_Handler(void); + JUMP_FUNCTION(CK802_TRAP_C) = (uint32_t)&sram_HardFault_Handler; //register trap irq handler #ifdef CONFIG_KERNEL_NONE _system_init_for_baremetal(); @@ -267,12 +273,13 @@ void SystemInit(void) hal_rfphy_init(); + int i = 0; PHY6220_Vectors[0] = (uint32_t)Reset_Handler; for (i = 1; i < 32; i++) { - PHY6220_Vectors[i] = (uint32_t)Default_Handler; + PHY6220_Vectors[i] = (uint32_t)sram_HardFault_Handler; } PHY6220_Vectors[32] = (uint32_t)tspend_handler; -- Gitee From a727cf911ad33c1ee56a4e9c7f8d40fe3128d2d0 Mon Sep 17 00:00:00 2001 From: "qing.han" Date: Mon, 8 Nov 2021 13:59:10 +0800 Subject: [PATCH 3/7] delete jump area init in sys resume mode --- pm.c | 1 + reboot.c | 2 -- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/pm.c b/pm.c index 4a0093a..6526692 100755 --- a/pm.c +++ b/pm.c @@ -701,6 +701,7 @@ void sram_reset_handler(void) } void just_enter_sleep(uint32 time) { + jump_area_init(); JUMP_FUNCTION(WAKEUP_PROCESS) = (uint32_t)sram_reset_handler; /* set sleep flag , rom boot will check the flag and diff --git a/reboot.c b/reboot.c index 207ffc4..0faf3a2 100755 --- a/reboot.c +++ b/reboot.c @@ -24,8 +24,6 @@ extern void sram_reset_handler(void); __attribute__((section(".__sram.code"))) void config_reset_handler(int rstMod) { - jump_area_init(); - if(rstMod==RST_FROM_ROM_BOOT) { set_sleep_flag(0); -- Gitee From 2b45f3d5614c8ec074ec6d2f4048007407586cd0 Mon Sep 17 00:00:00 2001 From: "qing.han" Date: Mon, 8 Nov 2021 14:17:43 +0800 Subject: [PATCH 4/7] fix build error --- pm.c | 177 +---------------------------------------------------------- 1 file changed, 2 insertions(+), 175 deletions(-) diff --git a/pm.c b/pm.c index b83b09c..4adc37c 100755 --- a/pm.c +++ b/pm.c @@ -641,167 +641,6 @@ int sys_soc_suspend(uint32_t suspend_tick) #ifndef BASE_TIME_UINTS #define BASE_TIME_UNITS (0x3fffff) #endif -extern uint8 rc32k_calibration(void); -#define CRY32_2_CYCLE_16MHZ_CYCLE_MAX (976 + 98) // tracking value range std +/- 20% -#define CRY32_2_CYCLE_16MHZ_CYCLE_MIN (976 - 98) -#define CRY32_2_CYCLE_DELTA_LMT (19) -#define TRACKING_96M_16M_MULTI6_DELTA_LIMIT (10*6) //96M:16M*6 +- 1% -#define DLL_ENABLE_MAX (5) - -volatile uint8_t g_rc32kCalRes = 0xFF; -uint32_t g_xtal16M_tmp=0; -uint32_t g_xtal96M_temp=0; -uint32_t DLL_enable_num=1; - -void rf_calibrate2(void) -{ - //========== do rf tp cal for tx and rx dcoffset cal - rf_phy_ana_cfg(); - rf_tpCal_gen_cap_arrary(); //generate the tpCal cap arrary - //rf_tpCal_cfg(/*rfChn*/2); - rf_rxDcoc_cfg(/*rfChn*/88,/*bwSet*/1,&g_rfPhyRxDcIQ); //set the rfChn as 2488 for BW=1MHz - g_rc32kCalRes = rc32k_calibration(); -} - -static void check_16MXtal_by_rcTracking(void) -{ - /* - for fiset wakeupini, not do rcCal, just skip the rcTacking - */ - if(g_rc32kCalRes==0xFF) - { - WaitRTCCount(60); - return; - } - - uint32_t temp,temp1; - uint32_t temp31,temp32,temp33; - uint32_t temp_min,temp_max; - - // ======== enable tracking 32KHz RC timer with 16MHz crystal clock - temp = *(volatile uint32_t *)0x4000f040; - *(volatile uint32_t *)0x4000f040 = temp | BIT(18); - temp = *(volatile uint32_t *)0x4000f05C; - *(volatile uint32_t *)0x4000f05C = (temp & 0xfffefe00) | 0x0028; - WaitRTCCount(3); - - temp31 = (*(volatile uint32_t *)0x4000f064 & 0x1ffff); - WaitRTCCount(3); - - temp32 = (*(volatile uint32_t *)0x4000f064 & 0x1ffff); - WaitRTCCount(3); - - temp33 = (*(volatile uint32_t *)0x4000f064 & 0x1ffff); - - while(1) - { - temp_min = (temp31 >=temp32) ? (temp32):(temp31); - temp_min = (temp_min >=temp33) ? (temp33):(temp_min); - temp_max = (temp31 >=temp32) ? (temp31):(temp32); - temp_max = (temp_max >=temp33) ? (temp_max):(temp33); - - if( temp31>CRY32_2_CYCLE_16MHZ_CYCLE_MIN && - temp31CRY32_2_CYCLE_16MHZ_CYCLE_MIN && - temp32 CRY32_2_CYCLE_16MHZ_CYCLE_MIN && - temp33 =temp1 ? (g_xtal16M_tmp*6 -temp1):(temp1-g_xtal16M_tmp*6))= DLL_ENABLE_MAX) - { - NVIC_SystemReset(); - } - - //disable DLL - - subWriteReg(0x4000f044,7,7,0); - WaitRTCCount(3); - - //update g_xtal16M_tmp - temp = *(volatile uint32_t *)0x4000f05C; - *(volatile uint32_t *)0x4000f05C = (temp & 0xfffefe00) | 0x0028 ; - WaitRTCCount(3); - g_xtal16M_tmp = (*(volatile uint32_t *)0x4000f064 & 0x1ffff); - - subWriteReg(0x4000f05C,3,3,0); - } - -} #define CRY32_2_CYCLE_16MHZ_CYCLE_MAX (976 + 98) // tracking value range std +/- 20% #define CRY32_2_CYCLE_16MHZ_CYCLE_MIN (976 - 98) @@ -1113,18 +952,6 @@ void wakeup_init1() { pGlobal_config[WAKEUP_ADVANCE] =1500+30*tracking_cnt; } - tracking_c2 = rtc_get_counter(); - - tracking_cnt = (tracking_c2>=tracking_c1) ? (tracking_c2-tracking_c1) : (0xffffffff-tracking_c1+tracking_c2); - - pGlobal_config[WAKEUP_ADVANCE] =1500+30*tracking_cnt; - - //enable DLL - uint32 temp0; - temp0 = *(volatile uint32_t *)0x4000f044; - *(volatile uint32_t *)0x4000f044 = temp0 | BIT(7); - WaitRTCCount(3); - } // ============ config BB Top *(volatile uint32_t *) 0x40030000 = 0x3d068001; // set tx pkt =2 *(volatile uint32_t *) 0x400300bc = 0x834; //[7:0] pll_tm [11:8] rxafe settle @@ -1170,7 +997,7 @@ extern void efuse_init(void); int sys_soc_resume(int pm_state) { uint32_t current_RTC_tick; uint32_t wakeup_time, wakeup_time0, next_time; - uint64_t sleep_total; + uint32_t sleep_total; uint32_t dlt_tick; if (pm_state == SYS_POWER_STATE_RUN) { @@ -1385,7 +1212,7 @@ int sys_soc_resume(int pm_state) { // ==== measure value, from RTC counter meet comparator 0 -> here : 260us ~ 270us // start task loop // osal_start_system(); - uint64_t sleep_total_us = sleep_total + g_osal_tick_trim; + uint32_t sleep_total_us = sleep_total + g_osal_tick_trim; sleep_total_us = ((sleep_total_us << 7) + (sleep_total_us << 1) + sleep_total_us) >> 17; //sleep_total_us/1000 return sleep_total_us; } -- Gitee From a61dbe1cfb8019a8ff6d0ada56787d3bf47a7ed6 Mon Sep 17 00:00:00 2001 From: "qing.han" Date: Thu, 11 Nov 2021 14:25:10 +0800 Subject: [PATCH 5/7] fix build warning --- components/driver/inc/gpio.h | 1 + components/driver/src/phy_adc.c | 5 ++--- csi_drivers/spif.c | 4 ++++ include/spif.h | 5 +++++ phy_pmu.c | 16 +++------------- pm.c | 17 ++++++++++++++--- reboot.c | 1 + system.c | 1 + 8 files changed, 31 insertions(+), 19 deletions(-) diff --git a/components/driver/inc/gpio.h b/components/driver/inc/gpio.h index 3176428..d23a22d 100755 --- a/components/driver/inc/gpio.h +++ b/components/driver/inc/gpio.h @@ -204,5 +204,6 @@ int phy_gpioretention_unregister(gpio_pin_e pin); int phy_gpioretention_register(gpio_pin_e pin); void phy_gpioretention_prepare_sleep_action(void); void phy_gpioretention_prepare_wakeup_action(void); +__attribute__((section(".__sram.code"))) void phy_gpioretention_disable(void); #endif diff --git a/components/driver/src/phy_adc.c b/components/driver/src/phy_adc.c index bf5c080..b8d641c 100755 --- a/components/driver/src/phy_adc.c +++ b/components/driver/src/phy_adc.c @@ -544,8 +544,6 @@ const unsigned short adc_Lambda[ADC_CH_NUM] = int phy_adc_value_cal(adc_CH_t ch, uint16_t *buf, uint32_t size, bool high_resol, bool diff_mode) { - uint32_t i; - int adc_sum = 0; volatile float result = 0.0; phy_adc_load_calibration_value(); @@ -888,7 +886,8 @@ static int read_multiple_channel_n(adc_handle_t handle, uint32_t *data, uint32_t ch_cur=(ch%2)?(ch-1):(ch+1); - i=(++i)%8; + ++i; + i&=0x07; adc_sum = 0; for (n = 0; n < 29; n++) { adc_sum += (uint16_t)(read_reg(ADC_CH_BASE + (ch_cur * 0x80) + ((n+2) * 4))&0xfff); diff --git a/csi_drivers/spif.c b/csi_drivers/spif.c index e1ff416..206a771 100755 --- a/csi_drivers/spif.c +++ b/csi_drivers/spif.c @@ -55,6 +55,10 @@ extern void spif_set_deep_sleep(void); extern void spif_release_deep_sleep(void); extern void spif_cmd(uint8_t op, uint8_t addrlen, uint8_t rdlen, uint8_t wrlen, uint8_t mbit, uint8_t dummy); extern void spif_rddata(uint8_t *data, uint8_t len); +extern void WaitRTCCount(uint32_t rtcDelyCnt); +extern uint8_t spif_flash_status_reg_0(void); +extern uint8_t spif_flash_status_reg_1(void); +extern void spif_wrdata(uint8_t* data, uint8_t len); #define SPIF_TIMEOUT 1000000 diff --git a/include/spif.h b/include/spif.h index 0077f3b..62add18 100755 --- a/include/spif.h +++ b/include/spif.h @@ -119,11 +119,16 @@ extern "C" { extern uint8_t spif_flash_status_reg_1(void); extern void spif_wrdata(uint8_t* data, uint8_t len); +__attribute__((section(".__sram.code"))) void hal_cache_tag_flush(void); + + __attribute__((section(".__sram.code"))) int hal_flash_rd_status_reg(uint8* buf,bool low_8bit); __attribute__((section(".__sram.code"))) int hal_flash_wr_status_reg(uint8* buf,int len); __attribute__((section(".__sram.code"))) int hal_flash_switch_hardware_protect_mode(void); __attribute__((section(".__sram.code"))) int hal_flash_switch_hardware_unprotect_mode(void); +__attribute__((section(".__sram.code"))) uint8_t hal_flash_write_disable(void); + #ifdef __cplusplus } diff --git a/phy_pmu.c b/phy_pmu.c index d14a02c..fa1d802 100755 --- a/phy_pmu.c +++ b/phy_pmu.c @@ -36,6 +36,7 @@ typedef struct { extern int32_t arch_do_cpu_save(void); extern int32_t arch_do_cpu_resume(void); +extern uint32_t rtc_get_counter(void); static uint8_t pmu_power_status; static phy_pmu_priv_t pmu_handle[CONFIG_PMU_NUM]; @@ -56,7 +57,6 @@ uint32_t g_arch_cpu_saved[CONFIG_CPU_REGISTER_NUM_SAVE]; static void do_prepare_sleep_action(int32_t idx) { int i = 0; - /* save vic register */ vic_regs_saved[0] = VIC->ISER[0U]; vic_regs_saved[1] = VIC->ISPR[0U]; @@ -66,12 +66,6 @@ static void do_prepare_sleep_action(int32_t idx) vic_regs_saved[3 + i] = VIC->IPR[i]; } - /* save irq priority reg */ - for (i = 0;i < 8; i++) - { - vic_regs_saved[3 + i] = VIC->IPR[i]; - } - /* save the coretim register */ cortim_regs_saved[0] = CORET->LOAD; cortim_regs_saved[1] = CORET->CTRL; @@ -92,12 +86,6 @@ static void do_wakeup_sleep_action(int32_t idx) VIC->IPR[i] = vic_regs_saved[3 + i]; } - /* resume irq priority reg */ - for (i = 0;i < 8; i++) - { - VIC->IPR[i] = vic_regs_saved[3 + i]; - } - /* resume the coretim register */ CORET->LOAD = cortim_regs_saved[0]; CORET->VAL = 0UL; @@ -214,6 +202,7 @@ int32_t csi_pmu_enter_sleep(pmu_handle_t handle, pmu_mode_e mode) if(((AP_AON->RTCCC0 - rtc_current)>(pGlobal_config[MAX_SLEEP_TIME]>>4)) || ((AP_AON->RTCCC0 - rtc_current)<(pGlobal_config[MIN_SLEEP_TIME]>>6))) { + extern void just_enter_sleep(uint32 time); just_enter_sleep(33000); } extern int32_t arch_do_cpu_resume(void); @@ -233,6 +222,7 @@ int32_t csi_pmu_enter_sleep(pmu_handle_t handle, pmu_mode_e mode) if (pmu_priv->cb) { pmu_priv->cb(pmu_priv->idx, PMU_EVENT_PREPARE_SLEEP, mode); } + set_sleep_flag(0); *((unsigned int *)0x4000f0c0) = 0x2; subWriteReg(0x4000f01c, 6, 6, 0x00); //disable software control enter_sleep_off_mode(SYSTEM_OFF_MODE); diff --git a/pm.c b/pm.c index 4adc37c..426f180 100755 --- a/pm.c +++ b/pm.c @@ -22,6 +22,7 @@ #include "pwrmgr.h" #include "pin.h" #include "pm.h" +#include "spif.h" #define DBGIO_LL_TRIG P14 #define DBGIO_LL_IRQ P15 @@ -65,6 +66,11 @@ extern uint32 read_LL_remainder_time(void); extern uint32_t read_current_fine_time(void); extern int clk_spif_ref_clk(sysclk_t spif_ref_sel); extern void hal_mpu_config(void); +extern void drv_reboot(int cmd); +extern void *osal_memcpy( void *dst, const void GENERIC *src, unsigned int len ); +extern void *osal_memset( void *dest, uint8 value, int len ); +extern __attribute__((section(".__sram.code"))) void config_reset_handler(int rstMod); +extern void jump_area_init(void); static uint32_t irq_flags; @@ -102,6 +108,10 @@ pm_wakeup_by_io_cb g_wakeup_cb = NULL; #define CONFIG_WDT 1 #endif +#ifndef CONFIG_LOW_POWER_WAKE_DEBUG +#define CONFIG_LOW_POWER_WAKE_DEBUG 0 +#endif + #if (CONFIG_WDT > 0) #define WDT_TIMEOUT 2000 static wdt_handle_t wdt_handle = NULL; @@ -472,6 +482,7 @@ int sys_soc_suspend(uint32_t suspend_tick) RHINO_CPU_INTRPT_DISABLE(); irq_flags = psr; + extern void check_hclk_by_rc32k_rtc(void); check_hclk_by_rc32k_rtc(); if (!isSleepAllowInPM()) { @@ -661,10 +672,10 @@ extern uint32_t g_system_reset_cause; void _rom_data_init(void) { //copy rom data section - osal_memcpy(0x1fff0800,0x17c7c,(0x1fff0924-0x1fff0800)); + osal_memcpy((void *)0x1fff0800,(const void GENERIC *)0x17c7c,(0x1fff0924-0x1fff0800)); //clr rom bss section skip g_top_trapstack - osal_memset(0x1fff0924,0,(0x1fff0988-0x1fff0924)); - osal_memset(0x1fff0b8c,0,(0x1fff1a3c-0x1fff0b8c)); + osal_memset((void *)0x1fff0924,0,(0x1fff0988-0x1fff0924)); + osal_memset((void *)0x1fff0b8c,0,(0x1fff1a3c-0x1fff0b8c)); } void sram_reset_handler(void) diff --git a/reboot.c b/reboot.c index 0faf3a2..f25fcb6 100755 --- a/reboot.c +++ b/reboot.c @@ -21,6 +21,7 @@ extern size_t cpu_intrpt_save(void); extern void sram_reset_handler(void); +extern void set_sleep_flag(int flag); __attribute__((section(".__sram.code"))) void config_reset_handler(int rstMod) { diff --git a/system.c b/system.c index bb68863..f806a73 100755 --- a/system.c +++ b/system.c @@ -35,6 +35,7 @@ #include "sys_freq.h" #include #include "pm.h" +#include "spif.h" #ifndef CONFIG_SYSTICK_HZ #define CONFIG_SYSTICK_HZ 100 -- Gitee From a795d27ca331c27f197a35e08b1e2087a7cb4026 Mon Sep 17 00:00:00 2001 From: "qing.han" Date: Wed, 17 Nov 2021 17:51:40 +0800 Subject: [PATCH 6/7] 1.add rtc tracking check and calibrate when enter sleep 2.add reboot function when trap --- components/controller/rf_phy_driver.h | 22 ++++++++++++++++++++++ components/driver/src/clock.c | 2 ++ pm.c | 25 +++++++++++++++++++++---- system.c | 4 +++- trap_c.c | 18 +++++++++++++++--- 5 files changed, 63 insertions(+), 8 deletions(-) diff --git a/components/controller/rf_phy_driver.h b/components/controller/rf_phy_driver.h index eacfe4b..b09f10e 100755 --- a/components/controller/rf_phy_driver.h +++ b/components/controller/rf_phy_driver.h @@ -208,6 +208,7 @@ extern volatile uint32_t g_dtmAccessCode ; #define PKT_FMT_BLR500K 3 #define PKT_FMT_BLR125K 4 +#ifdef CONFIG_CHIP_PACKAGE_QFN32 #define RF_PHY_TX_POWER_EXTRA_MAX 0x3f #define RF_PHY_TX_POWER_MAX 0x1f #define RF_PHY_TX_POWER_MIN 0x00 @@ -218,6 +219,27 @@ extern volatile uint32_t g_dtmAccessCode ; #define RF_PHY_TX_POWER_N5DBM 0x0a #define RF_PHY_TX_POWER_N20DBM 0x01 +#elif defined(CONFIG_CHIP_PACKAGE_SOP16) || defined(CONFIG_CHIP_PACKAGE_SOP24) + +#define RF_PHY_TX_POWER_EXTRA_MAX 0x3f +#define RF_PHY_TX_POWER_MAX 0x1f +#define RF_PHY_TX_POWER_MIN 0x00 + +#define RF_PHY_TX_POWER_5DBM 0x1d +#define RF_PHY_TX_POWER_4DBM 0x17 +#define RF_PHY_TX_POWER_3DBM 0x15 +#define RF_PHY_TX_POWER_0DBM 0x0d + +#define RF_PHY_TX_POWER_N2DBM 0x0a +#define RF_PHY_TX_POWER_N5DBM 0x06 +#define RF_PHY_TX_POWER_N6DBM 0x05 +#define RF_PHY_TX_POWER_N10DBM 0x03 +#define RF_PHY_TX_POWER_N15DBM 0x02 +#define RF_PHY_TX_POWER_N20DBM 0x01 +#else + #error "Please check chip package type" +#endif + #define RF_PHY_FREQ_FOFF_00KHZ 0 #define RF_PHY_FREQ_FOFF_20KHZ 5 #define RF_PHY_FREQ_FOFF_40KHZ 10 diff --git a/components/driver/src/clock.c b/components/driver/src/clock.c index f8a0d55..8d7b0f3 100755 --- a/components/driver/src/clock.c +++ b/components/driver/src/clock.c @@ -254,9 +254,11 @@ void hal_rtc_clock_config(CLK32K_e clk32Mode) subWriteReg(&(AP_AON->PMCTL0), 31, 27, 0x16); //pGlobal_config[LL_SWITCH]&=0xffffffee; } +#if !(defined(CONFIG_SYS_CLK_XTAL_16M) && CONFIG_SYS_CLK_XTAL_16M > 0) //ZQ 20200812 for rc32k wakeup subWriteReg(&(AP_AON->PMCTL0),28,28,0x1);//turn on 32kxtal subWriteReg(&(AP_AON->PMCTL1),18,17,0x0);// reduce 32kxtal bias current +#endif } uint32_t hal_systick(void) diff --git a/pm.c b/pm.c index 426f180..046702a 100755 --- a/pm.c +++ b/pm.c @@ -41,7 +41,7 @@ extern uint32_t g_wakeup_rtc_tick;// = 0; extern uint32_t sleep_flag;// = 0; // when sleep, set this value to SLEEP_MAGIC. when wakeup, set this value to 0 extern uint32_t osal_sys_tick; -extern uint32_t g_counter_traking_avg ;// = 3906; +extern uint32_t g_counter_traking_avg ;// = 3906;7812(bug fix 2021/11/15) extern volatile uint32_t llWaitingIrq; //used for sleep timer sync @@ -345,6 +345,22 @@ void set_sleep_flag(int flag) // *(volatile uint32_t *) 0x4000f024 |= 1 << 15; //enable comparator0 inerrupt //*(volatile uint32_t *) 0x4000f024 |= 0x148000; // combine above 3 statement to save MCU time +void rc32k_cap_cal(uint32_t temp) +{ + uint32_t rccap; + if((temp > CRY32_16_CYCLE_16MHZ_CYCLE_MAX) && ((*(volatile uint32_t *) 0x4000f018 & 0x7e) > 0)) + { + rccap = ((read_reg(0x4000f018)>>1) & 0x3f) - 1; + subWriteReg(0x4000f018,6,1,rccap); + WaitRTCCount(3); + } + else if((temp < CRY32_16_CYCLE_16MHZ_CYCLE_MIN) && ((*(volatile uint32_t *) 0x4000f018 & 0x7e) < 0x7e)) + { + rccap = ((read_reg(0x4000f018)>>1) & 0x3f) + 1; + subWriteReg(0x4000f018,6,1,rccap); + WaitRTCCount(3); + } +} void enterSleepProcess1(uint32_t time) { @@ -378,7 +394,8 @@ void enterSleepProcess1(uint32_t time) counter_tracking = (temp > CRY32_16_CYCLE_16MHZ_CYCLE_MAX) ? counter_tracking : temp; //20181204 filter the counter_tracking spur, due to the N+1 issue - + rc32k_cap_cal(temp); + if (g_counter_traking_cnt < 1000) { //before traking converage use hard limitation counter_tracking = (counter_tracking > CRY32_16_CYCLE_16MHZ_CYCLE_MAX || counter_tracking < CRY32_16_CYCLE_16MHZ_CYCLE_MIN) @@ -388,8 +405,8 @@ void enterSleepProcess1(uint32_t time) } else { //after tracking converage use soft limitation - counter_tracking = (counter_tracking > g_counter_traking_avg + (g_counter_traking_avg >> 8) - || counter_tracking < g_counter_traking_avg - (g_counter_traking_avg >> 8)) + counter_tracking = (counter_tracking > g_counter_traking_avg + (g_counter_traking_avg >> 3) + || counter_tracking < g_counter_traking_avg - (g_counter_traking_avg >> 3)) ? g_counter_traking_avg : counter_tracking; } diff --git a/system.c b/system.c index f806a73..7467e0c 100755 --- a/system.c +++ b/system.c @@ -202,7 +202,9 @@ static void hal_low_power_io_init(void) drv_pm_ram_retention(RET_SRAM0 | RET_SRAM1 | RET_SRAM2); //hal_pwrmgr_RAM_retention(RET_SRAM0); hal_pwrmgr_RAM_retention_set(); - //hal_pwrmgr_LowCurrentLdo_enable(); +#if (defined(CONFIG_SYS_CLK_XTAL_16M) && CONFIG_SYS_CLK_XTAL_16M > 0) + hal_pwrmgr_LowCurrentLdo_enable(); +#endif //========= low power module clk gate #if(PHY_MCU_TYPE==MCU_BUMBEE_CK802) *(volatile uint32_t *)0x40000008 = 0x001961f1; // diff --git a/trap_c.c b/trap_c.c index 0a764a7..2d1e126 100755 --- a/trap_c.c +++ b/trap_c.c @@ -27,6 +27,16 @@ #include void (*trap_c_callback)(void); +extern char * strerror(int errnum); +extern void drv_reboot(int cmd); + + +static void except_process_function(int errno, const char *file, int line, const char *func_name, void *caller) +{ + printf("Except! errno is %s, caller: %p\n", strerror(errno), caller); + drv_reboot(1); +} + void trap_c(uint32_t *regs) { @@ -47,9 +57,11 @@ void trap_c(uint32_t *regs) printf("epsr: %8x\n", regs[16]); printf("epc : %8x\n", regs[17]); - if (trap_c_callback) { - trap_c_callback(); - } + except_process_function(1, __FILE__, __LINE__, __func__, NULL); + +// if (trap_c_callback) { +// trap_c_callback(); +// } while (1); } -- Gitee From 7a4be72dc31d579d3f274e7dcc7198f0564e6bee Mon Sep 17 00:00:00 2001 From: "qing.han" Date: Tue, 29 Mar 2022 16:13:59 +0800 Subject: [PATCH 7/7] 1.change adc driver for polling mode 2.cost dowm sram in patch xip mode 3.bugfixed secondary adv/scan timing --- components/driver/src/phy_adc.c | 6 +- components/inc/types.h | 2 +- csi_drivers/spif.c | 127 +++++++++++++++++++------------- include/spif.h | 39 ++++++++++ misc/rom_sym_def.h | 3 + pm.c | 109 ++++++++++++++------------- reboot.c | 3 +- system.c | 4 +- 8 files changed, 185 insertions(+), 108 deletions(-) diff --git a/components/driver/src/phy_adc.c b/components/driver/src/phy_adc.c index b8d641c..a15dccb 100755 --- a/components/driver/src/phy_adc.c +++ b/components/driver/src/phy_adc.c @@ -222,7 +222,7 @@ int phy_adc_start_int_dis(void) //hal_pwrmgr_lock(MOD_ADCC); //JUMP_FUNCTION(V29_IRQ_HANDLER) = (uint32_t)&hal_ADC_IRQHandler; - MASK_ADC_INT; + AP_ADCC->intr_mask = 0x1ff; drv_irq_disable(ADCC_IRQn); drv_irq_unregister(ADCC_IRQn); @@ -885,6 +885,10 @@ static int read_multiple_channel_n(adc_handle_t handle, uint32_t *data, uint32_t break; ch_cur=(ch%2)?(ch-1):(ch+1); + + while(!(read_reg(0x4005003c)&BIT(ch_cur))); + + subWriteReg(0x40050038,ch_cur,ch_cur,1); ++i; i&=0x07; diff --git a/components/inc/types.h b/components/inc/types.h index d1c404b..1476922 100755 --- a/components/inc/types.h +++ b/components/inc/types.h @@ -169,7 +169,7 @@ typedef struct _comm_evt_t { typedef void (*comm_cb_t)(comm_evt_t *pev); - +#define __ATTR_FUNC_XIP__(fn) __attribute__(( section("__xip_function__."#fn))) fn #endif diff --git a/csi_drivers/spif.c b/csi_drivers/spif.c index 206a771..f737ee9 100755 --- a/csi_drivers/spif.c +++ b/csi_drivers/spif.c @@ -59,6 +59,7 @@ extern void WaitRTCCount(uint32_t rtcDelyCnt); extern uint8_t spif_flash_status_reg_0(void); extern uint8_t spif_flash_status_reg_1(void); extern void spif_wrdata(uint8_t* data, uint8_t len); +extern void ll_patch_restore(uint8_t flg); #define SPIF_TIMEOUT 1000000 @@ -102,6 +103,7 @@ __attribute__((section(".__sram.code"))) static inline uint32_t spif_lock() VIC->ICER[0] = 0xFFFFFFFF; //enable ll irq and tim1 irq VIC->ISER[0] = 0x100010; + ll_patch_restore(0); HAL_EXIT_CRITICAL_SECTION(); return vic_iser; } @@ -111,6 +113,7 @@ __attribute__((section(".__sram.code"))) static inline void spif_unlock(uint32_ _HAL_CS_ALLOC_(); HAL_ENTER_CRITICAL_SECTION(); VIC->ISER[0] = vic_iser; + ll_patch_restore(1); HAL_EXIT_CRITICAL_SECTION(); } @@ -193,16 +196,17 @@ __attribute__((section(".__sram.code"))) static int _spif_wait_nobusy_x(uint8_t return PPlus_ERR_BUSY; } -__attribute__((section(".__sram.code"))) uint8_t hal_flash_lock_status(void) +__attribute__((section(".__sram.code"))) uint16_t hal_flash_lock_status() { - uint8_t status = _spif_read_status_reg_x(); - return status&(FCMD_DATAPRO_AREA_512|FCMD_SRP_REG); - + uint16_t status = _spif_read_status_reg_x(); + if(s_spif_ctx.mid == FLASH_TH_ID) + return status&(FCMD_DATAPRO_AREA_512_TH | FCMD_SRP_REG_TH); + return status&(FCMD_DATAPRO_AREA_512 | FCMD_SRP_REG); } __attribute__((section(".__sram.code"))) uint8_t hal_flash_write_disable(void) { - uint32_t result = csi_irq_save(); + uint32_t cs = spif_lock(); uint8_t status; status = _spif_read_status_reg_x(); if(status & SFLG_WEL) @@ -211,34 +215,51 @@ __attribute__((section(".__sram.code"))) uint8_t hal_flash_write_disable(void) SPIF_STATUS_WAIT_IDLE(SPIF_WAIT_IDLE_CYC); spif_wait_nobusy(SFLG_WIP, SPIF_TIMEOUT, PPlus_ERR_BUSY); } - csi_irq_restore(result); + spif_unlock(cs); return 0; } -__attribute__((section(".__sram.code"))) int hal_flash_lock(uint8_t area) +__attribute__((section(".__sram.code"))) int hal_flash_lock(uint16_t area) { - uint32_t result = csi_irq_save(); - area &= FCMD_DATAPRO_AREA_512; - area |= FCMD_SRP_REG; + uint32_t cs = spif_lock(); + if(s_spif_ctx.mid == FLASH_TH_ID) + { + area |= FCMD_DATAPRO_AREA_512_TH; + area |= FCMD_SRP_REG_TH; + } + else + { + area &= FCMD_DATAPRO_AREA_512; + area |= FCMD_SRP_REG; + } if(area != hal_flash_lock_status()) { - SPIF_STATUS_WAIT_IDLE(SPIF_WAIT_IDLE_CYC); - spif_wait_nobusy(SFLG_WIP, SPIF_TIMEOUT, PPlus_ERR_BUSY); - AP_SPIF->fcmd = XFRD_FCMD_WREN; - SPIF_STATUS_WAIT_IDLE(SPIF_WAIT_IDLE_CYC); - spif_wait_nobusy(SFLG_WIP, SPIF_TIMEOUT, PPlus_ERR_BUSY); - AP_SPIF->fcmd_wrdata[0] = area | FCMD_SRP_REG; - AP_SPIF->fcmd = XFRD_FCMD_WRST; - SPIF_STATUS_WAIT_IDLE(SPIF_WAIT_IDLE_CYC); - spif_wait_nobusy(SFLG_WIP, SPIF_TIMEOUT, PPlus_ERR_BUSY); + if(s_spif_ctx.mid == FLASH_TH_ID) + { + area |= FCMD_SRP_REG_TH; + hal_flash_wr_status_reg((uint8 *)&area,2); + + } + else + { + SPIF_STATUS_WAIT_IDLE(SPIF_WAIT_IDLE_CYC); + spif_wait_nobusy(SFLG_WIP, SPIF_TIMEOUT, PPlus_ERR_BUSY); + AP_SPIF->fcmd = XFRD_FCMD_WREN; + SPIF_STATUS_WAIT_IDLE(SPIF_WAIT_IDLE_CYC); + spif_wait_nobusy(SFLG_WIP, SPIF_TIMEOUT, PPlus_ERR_BUSY); + AP_SPIF->fcmd_wrdata[0] = area | FCMD_SRP_REG; + AP_SPIF->fcmd = XFRD_FCMD_WRST; + SPIF_STATUS_WAIT_IDLE(SPIF_WAIT_IDLE_CYC); + spif_wait_nobusy(SFLG_WIP, SPIF_TIMEOUT, PPlus_ERR_BUSY); + } } - csi_irq_restore(result); + spif_unlock(cs); return 0; } - -__attribute__((section(".__sram.code"))) int hal_flash_unlock(void) -{ - uint32_t result = csi_irq_save(); +__attribute__((section(".__sram.code"))) int hal_flash_unlock() +{ + + uint32_t cs = spif_lock(); if(FCMD_DATAPRO_AREA_NONE != hal_flash_lock_status()) { @@ -253,7 +274,7 @@ __attribute__((section(".__sram.code"))) int hal_flash_unlock(void) SPIF_STATUS_WAIT_IDLE(SPIF_WAIT_IDLE_CYC); spif_wait_nobusy(SFLG_WIP, SPIF_TIMEOUT, PPlus_ERR_BUSY); } - csi_irq_restore(result); + spif_unlock(cs); return 0; } @@ -261,9 +282,7 @@ __attribute__((section(".__sram.code"))) int hal_flash_unlock(void) __attribute__((section(".__sram.code"))) static int hal_flash_write(uint32_t addr, uint8_t *data, uint32_t size) { uint8_t retval; - - uint32_t result = csi_irq_save(); - //hal_flash_unlock(); + uint32_t cs = spif_lock(); HAL_CACHE_ENTER_BYPASS_SECTION(); SPIF_STATUS_WAIT_IDLE(SPIF_WAIT_IDLE_CYC); spif_wait_nobusy(SFLG_WIP, SPIF_TIMEOUT, PPlus_ERR_BUSY); @@ -272,14 +291,13 @@ __attribute__((section(".__sram.code"))) static int hal_flash_write(uint32_t ad SPIF_STATUS_WAIT_IDLE(SPIF_WAIT_IDLE_CYC); spif_wait_nobusy(SFLG_WIP, SPIF_TIMEOUT, PPlus_ERR_BUSY); HAL_CACHE_EXIT_BYPASS_SECTION(); - //hal_flash_lock(); - csi_irq_restore(result); + spif_unlock(cs); return retval; } __attribute__((section(".__sram.code"))) static int hal_flash_read(uint32_t addr, uint8_t *data, uint32_t size) { - uint32_t result = csi_irq_save(); + uint32_t cs = spif_lock(); volatile uint8_t *u8_spif_addr = (volatile uint8_t *)((addr & 0x7ffff) | SPIF_ADDR_START); uint32_t cb = AP_PCR->CACHE_BYPASS; //#if(SPIF_FLASH_SZIE == FLASH_SIZE_1MB) @@ -319,8 +337,7 @@ __attribute__((section(".__sram.code"))) static int hal_flash_read(uint32_t add #endif -// spif_unlock(cs); - csi_irq_restore(result); + spif_unlock(cs); return PPlus_SUCCESS; } @@ -328,9 +345,8 @@ __attribute__((section(".__sram.code"))) static int hal_flash_read(uint32_t add __attribute__((section(".__sram.code"))) int hal_flash_erase_sector(unsigned int addr) { uint8_t retval; - - uint32_t result = csi_irq_save(); - //hal_flash_unlock(); + uint32_t cs = spif_lock(); + uint32_t cb = AP_PCR->CACHE_BYPASS; SPIF_STATUS_WAIT_IDLE(SPIF_WAIT_IDLE_CYC); @@ -343,8 +359,7 @@ __attribute__((section(".__sram.code"))) int hal_flash_erase_sector(unsigned in hal_cache_tag_flush(); } - //hal_flash_lock(); - csi_irq_restore(result); + spif_unlock(cs); return retval; } @@ -352,9 +367,8 @@ __attribute__((section(".__sram.code"))) int hal_flash_erase_sector(unsigned in __attribute__((section(".__sram.code"))) int hal_flash_erase_block64(unsigned int addr) { uint8_t retval; - - uint32_t result = csi_irq_save(); - //hal_flash_unlock(); + uint32_t cs = spif_lock(); + uint32_t cb = AP_PCR->CACHE_BYPASS; SPIF_STATUS_WAIT_IDLE(SPIF_WAIT_IDLE_CYC); spif_wait_nobusy(SFLG_WIP, SPIF_TIMEOUT, PPlus_ERR_BUSY); @@ -365,17 +379,16 @@ __attribute__((section(".__sram.code"))) int hal_flash_erase_block64(unsigned i hal_cache_tag_flush(); } - //hal_flash_lock(); - csi_irq_restore(result); + spif_unlock(cs); + return retval; } __attribute__((section(".__sram.code"))) int hal_flash_erase_all(void) { uint8_t retval; - uint32_t result = csi_irq_save(); - - //hal_flash_unlock(); + uint32_t cs = spif_lock(); + uint32_t cb = AP_PCR->CACHE_BYPASS; SPIF_STATUS_WAIT_IDLE(SPIF_WAIT_IDLE_CYC); spif_wait_nobusy(SFLG_WIP, SPIF_TIMEOUT, PPlus_ERR_BUSY); @@ -386,12 +399,19 @@ __attribute__((section(".__sram.code"))) int hal_flash_erase_all(void) hal_cache_tag_flush(); } - //hal_flash_lock(); - csi_irq_restore(result); + spif_unlock(cs); return retval; } +__attribute__((section(".__sram.code")))uint16_t hal_flash_area_choose() +{ + uint16_t area = FCMD_DATAPRO_AREA_384; + if(s_spif_ctx.mid == FLASH_TH_ID) + area = FCMD_DATAPRO_AREA_384_TH | FCMD_DATAPRO_AREA_384_TH_CMP; + return area; +} + /* basic spif driver */ @@ -460,7 +480,7 @@ uint32_t phy_flash_block64_erase(unsigned int addr) __attribute__((section(".__sram.code"))) int hal_flash_rd_status_reg(uint8* buf,bool low_8bit) { uint8_t retval = PPlus_SUCCESS; - uint32_t result = csi_irq_save(); + uint32_t cs = spif_lock(); SPIF_STATUS_WAIT_IDLE(SPIF_WAIT_IDLE_CYC); spif_wait_nobusy(SFLG_WIP, SPIF_TIMEOUT, PPlus_ERR_BUSY); @@ -475,7 +495,7 @@ __attribute__((section(".__sram.code"))) int hal_flash_rd_status_reg(uint8* buf, } SPIF_STATUS_WAIT_IDLE(SPIF_WAIT_IDLE_CYC); spif_wait_nobusy(SFLG_WIP, SPIF_TIMEOUT, PPlus_ERR_BUSY); - csi_irq_restore(result); + spif_unlock(cs); return retval; } @@ -483,14 +503,14 @@ __attribute__((section(".__sram.code"))) int hal_flash_rd_status_reg(uint8* buf, __attribute__((section(".__sram.code"))) int hal_flash_wr_status_reg(uint8* buf,int len) { uint8_t retval = PPlus_SUCCESS; - uint32_t result; + //uint32_t result; if((len != 1) && (len != 2)) { return PPlus_ERR_INVALID_PARAM; } - result = csi_irq_save(); + uint32_t cs = spif_lock(); SPIF_STATUS_WAIT_IDLE(SPIF_WAIT_IDLE_CYC); spif_wait_nobusy(SFLG_WIP, SPIF_TIMEOUT, PPlus_ERR_BUSY); @@ -504,7 +524,7 @@ __attribute__((section(".__sram.code"))) int hal_flash_wr_status_reg(uint8* buf, spif_wait_nobusy(SFLG_WIP, SPIF_TIMEOUT, PPlus_ERR_BUSY); SPIF_STATUS_WAIT_IDLE(SPIF_WAIT_IDLE_CYC); - csi_irq_restore(result); + spif_unlock(cs); return retval; } @@ -914,3 +934,4 @@ int32_t csi_spiflash_power_control(spiflash_handle_t handle, /*csi_power_stat_e* return state; } + diff --git a/include/spif.h b/include/spif.h index 62add18..5cff3a6 100755 --- a/include/spif.h +++ b/include/spif.h @@ -25,6 +25,7 @@ //#include "drv_spiflash.h" //#include "soc.h" #include "types.h" +#include "rom_sym_def.h" #ifdef __cplusplus extern "C" { @@ -35,6 +36,27 @@ extern "C" { #define __IOM volatile /*! Defines 'read / write' structure member permissions */ #endif +typedef struct{ + uint8_t state; + uint32_t size; + + bool w_protect; + + uint8_t clk_div; + + uint32_t qspi_en; + uint32_t rd_instr; + uint32_t wr_instr; + uint32_t remap; + + /*device id*/ + uint8_t mid; + uint8_t mtype; //mempry type + uint8_t mcapc; //memory capcity +}spif_ctx_t; + +extern spif_ctx_t s_spif_ctx; + #define CONFIG_SPIFLASH_NUM 1 #define DEBUG_EN 1 //#define SPIF_ADDR_START 0x11005000 @@ -59,6 +81,7 @@ extern "C" { + #define FCMD_RESET 0x99 //reset #define FCMD_ENRST 0x66 //enable reset #define FCMD_WREN 0x06 //write enable @@ -88,14 +111,21 @@ extern "C" { #define FCMD_CMD_EXCUTE 0x01 #define FCMD_SRP_REG 0x80 +#define FCMD_SRP_REG_TH 0x0080 + #define FCMD_DATAPRO_AREA_NONE 0x00 #define FCMD_DATAPRO_AREA_504 0x04 #define FCMD_DATAPRO_AREA_496 0x08 #define FCMD_DATAPRO_AREA_480 0x0c #define FCMD_DATAPRO_AREA_448 0x10 #define FCMD_DATAPRO_AREA_384 0x14 +#define FCMD_DATAPRO_AREA_384_TH 0x0008 +#define FCMD_DATAPRO_AREA_384_TH_CMP 0x4000 #define FCMD_DATAPRO_AREA_256 0x18 #define FCMD_DATAPRO_AREA_512 0x1c +#define FCMD_DATAPRO_AREA_512_TH 0x0000 + + #define FCMD_DATAPRO_NONE_BIT 0x00 #define FCMD_DATAPRO_504_BIT 0x04 @@ -107,6 +137,8 @@ extern "C" { #define FCMD_DATAPRO_512_BIT 0x1c + + #define FLASH_STATUS_REGISTER_LEN 1 #define XFRD_FCMD_WREN 0x6000001 @@ -116,7 +148,14 @@ extern "C" { #define FLASH_WP_LOW_LEVEL (AP_SPIF->config |= (1<<14)) #define FLASH_WP_LEVEL_GET (0x4000-(AP_SPIF->config & (1<<14))) +#define FLASH_GD_ID 0xc8 +#define FLASH_XTX_ID 0x0b +#define FLASH_TH_ID 0xcd + + + extern uint8_t spif_flash_status_reg_1(void); +extern int spif_read_id(uint32_t* pid); extern void spif_wrdata(uint8_t* data, uint8_t len); __attribute__((section(".__sram.code"))) void hal_cache_tag_flush(void); diff --git a/misc/rom_sym_def.h b/misc/rom_sym_def.h index 2cc7539..0e106ac 100755 --- a/misc/rom_sym_def.h +++ b/misc/rom_sym_def.h @@ -42,6 +42,7 @@ #define conn_param _symrom_conn_param #define connUpdateTimer _symrom_connUpdateTimer #define counter_tracking _symrom_counter_tracking +#define g_llScanMode _symrom_g_llScanMode #define crc16_rom _symrom_crc16 #define ctrlToHostEnable _symrom_ctrlToHostEnable #define dataPkt _symrom_dataPkt @@ -875,6 +876,7 @@ #define spif_set_deep_sleep _symrom_spif_set_deep_sleep #define spif_wrdata _symrom_spif_wrdata #define spif_write _symrom_spif_write +#define spif_read_id _symrom_spif_read_id #define spif_write_protect _symrom_spif_write_protect #define sram_ret_patch _symrom_sram_ret_patch #define supportedCmdsTable _symrom_supportedCmdsTable @@ -919,6 +921,7 @@ #define llProcessSlaveControlPacket0 _symrom_llProcessSlaveControlPacket0 #define llProcessMasterControlPacket0 _symrom_llProcessMasterControlPacket0 #define LL_slave_conn_event0 _symrom_LL_slave_conn_event0 +#define LL_SetScanParam0 _symrom_LL_SetScanParam0 #endif #endif diff --git a/pm.c b/pm.c index 046702a..fdfe7dc 100755 --- a/pm.c +++ b/pm.c @@ -34,6 +34,7 @@ #define MIN_TIME_TO_SLEEP 50 //ms #define MIN_TIME_TO_SUSPEND 10000 //ms + extern int g_spif_ref_clk; //pwrmgr_attribute_t pwrmgr_attribute; extern uint32_t ll_remain_time; @@ -371,7 +372,7 @@ void enterSleepProcess1(uint32_t time) if (pGlobal_config[LL_SWITCH] & RC32_TRACKINK_ALLOW) { // 1. read RC 32KHz tracking counter, calculate 16MHz ticks number per RC32KHz cycle - temp = *(volatile uint32_t *)0x4000f064 & 0x1ffff; + temp = AP_PCRM->cal_ro1 & 0x1ffff; //====== assume the error cnt is (n+1/2) cycle,for this case, it should be 9 or 10 // error_delt = (temp>STD_CRY32_8_CYCLE_16MHZ_CYCLE) @@ -722,13 +723,16 @@ void sram_reset_handler(void) g_system_reset_cause |=0x80; //check just_sleep_reset flg - if((((*(volatile uint32_t*)0x4000f0c4) & 0x0f)>>2)) + if(((AP_AON->SLEEP_R[1] & 0x0f)>>2)) g_system_reset_cause |=0x40; Reset_Handler(); } void just_enter_sleep(uint32 time) { + if (time < MIN_TIME_TO_SLEEP) + time = MIN_TIME_TO_SLEEP; + jump_area_init(); JUMP_FUNCTION(WAKEUP_PROCESS) = (uint32_t)sram_reset_handler; @@ -739,7 +743,7 @@ void just_enter_sleep(uint32 time) subWriteReg(&(AP_AON->PMCTL2_0),6,6,0x00); //disable software control // config wakeup timer - uint32_t sleep_tick_now = *(volatile uint32_t *) 0x4000f028; + uint32_t sleep_tick_now = AP_AON->RTCCNT; WaitRTCCount(1); AP_AON->RTCCC0 = sleep_tick_now + time; AP_AON->RTCCTL |= BIT(15)|BIT(18)|BIT(20); @@ -751,6 +755,9 @@ void just_enter_sleep(uint32 time) config reset casue as RSTC_WARM_NDWC reset path walkaround dwc */ + if (((AP_AON->SLEEP_R[1] & 0xFF00) >>8) > 100) + AP_AON->SLEEP_R[1]=0; + AP_AON->SLEEP_R[0]=4; // trigger system sleep @@ -769,7 +776,7 @@ void check_hclk_by_rc32k_rtc(void) uint32_t t1 = read_current_fine_time(); if((TIME_DELTA(t1,t0)RTC_32KRC_3_CYCLE_LIMIT_HIGH)) { - subWriteReg(0x4000f03c, 2, 0, 0); //switch hclk to RC32M + subWriteReg(&(AP_PCRM->CLKSEL), 2, 0, 0); //switch hclk to RC32M just_enter_sleep(33000); } @@ -785,7 +792,7 @@ void check_16MXtal_by_rcTracking(void) for fiset wakeupini, not do rcCal, just skip the rcTacking */ - if(((*(volatile uint32_t*)0x4000f0c4) & 0x80) == 0) + if((AP_AON->SLEEP_R[1] & 0x80) == 0) { WaitRTCCount(60); return; @@ -798,19 +805,19 @@ void check_16MXtal_by_rcTracking(void) uint32_t temp_min,temp_max; // ======== enable tracking 32KHz RC timer with 16MHz crystal clock - temp = *(volatile uint32_t *)0x4000f040; - *(volatile uint32_t *)0x4000f040 = temp | BIT(18); - temp = *(volatile uint32_t *)0x4000f05C; - *(volatile uint32_t *)0x4000f05C = (temp & 0xfffefe00) | 0x0028; + temp = AP_PCRM->CLKHF_CTL0; + AP_PCRM->CLKHF_CTL0 = temp | BIT(18); + temp = AP_PCRM->cal_rw; + AP_PCRM->cal_rw = (temp & 0xfffefe00) | 0x0028; WaitRTCCount(3); - temp31 = (*(volatile uint32_t *)0x4000f064 & 0x1ffff); + temp31 = (AP_PCRM->cal_ro1 & 0x1ffff); WaitRTCCount(3); - temp32 = (*(volatile uint32_t *)0x4000f064 & 0x1ffff); + temp32 = (AP_PCRM->cal_ro1 & 0x1ffff); WaitRTCCount(3); - temp33 = (*(volatile uint32_t *)0x4000f064 & 0x1ffff); + temp33 = (AP_PCRM->cal_ro1 & 0x1ffff); while(1) { @@ -828,27 +835,27 @@ void check_16MXtal_by_rcTracking(void) (temp_max-temp_min)SLEEP_R[1]),3,2,0); //reset tracking sleep num - subWriteReg(0x4000f0c4,15,8,0); + subWriteReg(&(AP_AON->SLEEP_R[1]),15,8,0); break; } temp31= temp32; temp32 = temp33; WaitRTCCount(3); - temp33 = (*(volatile uint32_t *)0x4000f064 & 0x1ffff); + temp33 = (AP_PCRM->cal_ro1 & 0x1ffff); //check tracking cost uint32_t tracking_end = rtc_get_counter(); uint32_t tracking_16M_tick = (tracking_end>=tracking_start) ? (tracking_end-tracking_start) : (0xffffffff-tracking_start+tracking_end); if(tracking_16M_tick >= TRACKING_16M_TICK_MAX) { - uint32_t tracking_sleep_num = (*(volatile uint32_t*)0x4000f0c4 & 0xFF00) >>8; - subWriteReg(0x4000f0c4,15,8,tracking_sleep_num+1); - subWriteReg(0x4000f0c4,3,2,1); - if ((1 << tracking_sleep_num)*33000< TRACKING_MAX_SLEEPTIME) + uint32_t tracking_sleep_num = (AP_AON->SLEEP_R[1] & 0xFF00) >>8; + subWriteReg(&(AP_AON->SLEEP_R[1]),15,8,tracking_sleep_num+1); + subWriteReg(&(AP_AON->SLEEP_R[1]),3,2,1); + if ((uint32_t)((uint32_t)1 << tracking_sleep_num)*33000 < TRACKING_MAX_SLEEPTIME) { just_enter_sleep((1 << tracking_sleep_num)*33000); } @@ -860,9 +867,9 @@ void check_16MXtal_by_rcTracking(void) } - temp1 = (*(volatile uint32_t *)0x4000f064 & 0x1ffff); + temp1 = (AP_PCRM->cal_ro1 & 0x1ffff); - subWriteReg(0x4000f05C,3,3,0); + subWriteReg(&(AP_PCRM->cal_rw),3,3,0); g_xtal16M_tmp = temp1; } @@ -872,11 +879,11 @@ void check_96MXtal_by_rcTracking(void) uint32_t temp,temp1; //for first wakeupinit - if(((*(volatile uint32_t*)0x4000f0c4) & 0x80) == 0) + if((AP_AON->SLEEP_R[1] & 0x80) == 0) { //enable DLL - temp = *(volatile uint32_t *)0x4000f044; - *(volatile uint32_t *)0x4000f044 = temp | BIT(7); + temp = AP_PCRM->CLKHF_CTL1; + AP_PCRM->CLKHF_CTL1 = temp | BIT(7); WaitRTCCount(3); return; } @@ -884,64 +891,64 @@ void check_96MXtal_by_rcTracking(void) DLL_enable_num=0; // ======== enable tracking 32KHz RC timer with 16MHz crystal clock - temp = *(volatile uint32_t *)0x4000f040; - *(volatile uint32_t *)0x4000f040 = temp | BIT(18); + temp = AP_PCRM->CLKHF_CTL0; + AP_PCRM->CLKHF_CTL0 = temp | BIT(18); while(1) { //enable DLL - temp = *(volatile uint32_t *)0x4000f044; - *(volatile uint32_t *)0x4000f044 = temp | BIT(7); + temp = AP_PCRM->CLKHF_CTL1; + AP_PCRM->CLKHF_CTL1 = temp | BIT(7); WaitRTCCount(3); DLL_enable_num++; // //enable digclk 96M - temp = *(volatile uint32_t *)0x4000f044; - *(volatile uint32_t *)0x4000f044 = temp | BIT(16); + temp = AP_PCRM->CLKHF_CTL1; + AP_PCRM->CLKHF_CTL1 = temp | BIT(16); for(uint8 index=0;index<5;index++) { - temp = *(volatile uint32_t *)0x4000f05C; - *(volatile uint32_t *)0x4000f05C = (temp & 0xfffefe00) | 0x0028 | BIT(16); + temp = AP_PCRM->cal_rw; + AP_PCRM->cal_rw = (temp & 0xfffefe00) | 0x0028 | BIT(16); WaitRTCCount(3); - temp1 = (*(volatile uint32_t *)0x4000f064 & 0x1ffff); - subWriteReg(0x4000f05C,3,3,0); + temp1 = (AP_PCRM->cal_ro1 & 0x1ffff); + subWriteReg(&(AP_PCRM->cal_rw),3,3,0); if( (g_xtal16M_tmp*6 >=temp1 ? (g_xtal16M_tmp*6 -temp1):(temp1-g_xtal16M_tmp*6))cal_rw),16,16,0); + subWriteReg(&(AP_PCRM->CLKHF_CTL1),16,16,0); g_xtal96M_temp = temp1; - subWriteReg(0x4000f0c4,5,4,0); + subWriteReg(&(AP_AON->SLEEP_R[1]),5,4,0); return; } } //disable 96M - subWriteReg(0x4000f05C,16,16,0); - subWriteReg(0x4000f044,16,16,0); + subWriteReg(&(AP_PCRM->cal_rw),16,16,0); + subWriteReg(&(AP_PCRM->CLKHF_CTL1),16,16,0); //should not be here if(DLL_enable_num>= DLL_ENABLE_MAX) { - subWriteReg(0x4000f0c4,5,4,1); + subWriteReg(&(AP_AON->SLEEP_R[1]),5,4,1); just_enter_sleep(60); } //disable DLL - subWriteReg(0x4000f044,7,7,0); + subWriteReg(&(AP_PCRM->CLKHF_CTL1),7,7,0); WaitRTCCount(3); //update g_xtal16M_tmp - temp = *(volatile uint32_t *)0x4000f05C; - *(volatile uint32_t *)0x4000f05C = (temp & 0xfffefe00) | 0x0028 ; + temp = AP_PCRM->cal_rw; + AP_PCRM->cal_rw = (temp & 0xfffefe00) | 0x0028 ; WaitRTCCount(3); - g_xtal16M_tmp = (*(volatile uint32_t *)0x4000f064 & 0x1ffff); + g_xtal16M_tmp = (AP_PCRM->cal_ro1 & 0x1ffff); - subWriteReg(0x4000f05C,3,3,0); + subWriteReg(&(AP_PCRM->cal_rw),3,3,0); } } @@ -969,12 +976,12 @@ void wakeup_init1() { uint32_t tracking_c1,tracking_c2; tracking_c1 = rtc_get_counter(); WaitRTCCount(30); - subWriteReg(0x4000f0c4,1,0,0); + subWriteReg(&(AP_AON->SLEEP_R[1]),1,0,0); check_16MXtal_by_rcTracking(); WaitRTCCount(6); - subWriteReg(0x4000f0c4,1,0,1); + subWriteReg(&(AP_AON->SLEEP_R[1]),1,0,1); check_96MXtal_by_rcTracking(); - subWriteReg(0x4000f0c4,1,0,2); + subWriteReg(&(AP_AON->SLEEP_R[1]),1,0,2); tracking_c2 = rtc_get_counter(); tracking_cnt = (tracking_c2>=tracking_c1) ? (tracking_c2-tracking_c1) : (0xffffffff-tracking_c1+tracking_c2); pGlobal_config[WAKEUP_ADVANCE] =1500+30*tracking_cnt; @@ -986,7 +993,7 @@ void wakeup_init1() { *(volatile uint32_t *) 0x400300a4 = 0x140; //[6] for tpm_en clk_init(g_system_clk); - subWriteReg(0x4000f0c4,1,0,3); + subWriteReg(&(AP_AON->SLEEP_R[1]),1,0,3); hal_wakeup_irq_config(); // ========== init timers @@ -1010,8 +1017,8 @@ void wakeup_init1() { ll_hw_ign_rfifo(LL_HW_IGN_SSN | LL_HW_IGN_CRC | LL_HW_IGN_EMP); // ======== enable tracking 32KHz RC timer with 16MHz crystal clock - temp = *(volatile uint32_t *)0x4000f05C; - *(volatile uint32_t *)0x4000f05C = (temp & 0xfffefe00) | 0x0108; //[16] 16M [8:4] cnt [3] track_en_rc32k + temp = AP_PCRM->cal_rw; + AP_PCRM->cal_rw = (temp & 0xfffefe00) | 0x0108; //[16] 16M [8:4] cnt [3] track_en_rc32k } static void hw_spif_cache_config(void) { diff --git a/reboot.c b/reboot.c index f25fcb6..3c2a4bb 100755 --- a/reboot.c +++ b/reboot.c @@ -55,7 +55,8 @@ __attribute__((section(".__sram.code"))) void drv_reboot(int cmd) reset path walkaround dwc */ AP_AON->SLEEP_R[0]=4; - + + AP_AON->SLEEP_R[1]=0; *(volatile uint32_t *) 0x40000004 = 0x00; diff --git a/system.c b/system.c index 7467e0c..8deb935 100755 --- a/system.c +++ b/system.c @@ -48,6 +48,7 @@ extern uint32_t g_system_clk; volatile uint8 g_clk32K_config; + extern int32_t g_top_irqstack; extern void irq_vectors_init(void); extern void init_config(void); @@ -300,7 +301,8 @@ void SystemInit(void) //replace TS_PEND IRQ with IRQ0 drv_irq_enable(0); - csi_vic_set_prio(0, 3); + csi_vic_set_prio(0, 3); + spif_read_id(NULL); hal_cache_init(); hal_mpu_config(); -- Gitee