BLE_TYQ_BJQ_CH584M/StdPeriphDriver/CH58x_sys.c

620 lines
14 KiB
C
Raw Permalink Normal View History

2024-12-03 11:11:30 +08:00
/********************************** (C) COPYRIGHT *******************************
* File Name : CH58x_SYS.c
* Author : WCH
* Version : V1.2
* Date : 2021/11/17
* Description : source file(ch585/ch584)
*********************************************************************************
* Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd.
* Attention: This software (modified or not) and binary are used for
* microcontroller manufactured by Nanjing Qinheng Microelectronics.
*******************************************************************************/
#include "CH58x_common.h"
2024-12-07 17:09:36 +08:00
#include "bsp_uart.h"
2024-12-03 11:11:30 +08:00
volatile MachineMode_Call_func gs_machine_mode_func;
extern uint32_t _vector_base[];
/*********************************************************************
* @fn SetSysClock
*
* @brief <EFBFBD><EFBFBD><EFBFBD><EFBFBD>ϵͳ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><EFBFBD>
*
* @param sc - ϵͳʱ<EFBFBD><EFBFBD>Դѡ<EFBFBD><EFBFBD> refer to SYS_CLKTypeDef
*
* @return none
*/
__HIGH_CODE
void SetSysClock(SYS_CLKTypeDef sc)
{
uint16_t clk_sys_cfg;
uint8_t i;
uint8_t x32M_c;
R32_SAFE_MODE_CTRL |= RB_XROM_312M_SEL;
R8_SAFE_MODE_CTRL &= ~RB_SAFE_AUTO_EN;
sys_safe_access_enable();
if(sc == RB_CLK_SYS_MOD) // 32KHz
{
R16_CLK_SYS_CFG |= RB_CLK_SYS_MOD;
}
else
{
if(sc & RB_OSC32M_SEL)
{
if(!(R8_HFCK_PWR_CTRL & RB_CLK_XT32M_PON))
{
x32M_c = R8_XT32M_TUNE;
R8_XT32M_TUNE |= 0x03;
R8_HFCK_PWR_CTRL |= RB_CLK_XT32M_PON;
clk_sys_cfg = R16_CLK_SYS_CFG;
R16_CLK_SYS_CFG |= 0xC0;
for(i=0; i<9; i++)
{
__nop();
}
R16_CLK_SYS_CFG = clk_sys_cfg;
R8_XT32M_TUNE = x32M_c;
}
}
else
{
R8_HFCK_PWR_CTRL |= RB_CLK_RC16M_PON;
}
if(sc & RB_XROM_SCLK_SEL) // PLL div
{
R8_HFCK_PWR_CTRL |= RB_CLK_PLL_PON;
if((sc&0x1F) == 0 )
{
R8_FLASH_SCK = R8_FLASH_SCK|(1<<4);
R8_FLASH_CFG = 0X07;
}
else if((sc&0x1F) < 10)
{
R8_FLASH_SCK = R8_FLASH_SCK & (~(1<<4));
R8_FLASH_CFG = 0X01;
}
else if((sc&0x1F) < 16)
{
R8_FLASH_SCK = R8_FLASH_SCK & (~(1<<4));
R8_FLASH_CFG = 0X02;
}
else
{
R8_FLASH_SCK = R8_FLASH_SCK|(1<<4);
R8_FLASH_CFG = 0X03;
}
}
else
{
if((sc&0x1F) < 8 )
{
R8_FLASH_SCK = R8_FLASH_SCK & (~(1<<4));
R8_FLASH_CFG = 0X51;
}
else
{
R8_FLASH_SCK = R8_FLASH_SCK & (~(1<<4));
R8_FLASH_CFG = 0X57;
}
}
R16_CLK_SYS_CFG = sc|0xC0;
R16_CLK_SYS_CFG = sc;
if(sc & RB_OSC32M_SEL)
{
if((!((R8_GLOB_CFG_INFO & RB_CFG_DEBUG_EN)|(R8_GLOB_CFG_INFO & RB_CFG_ROM_READ ))) && (R8_SAFE_DEBUG_CTRL & RB_DEBUG_DIS))
{
R8_HFCK_PWR_CTRL &= ~RB_CLK_RC16M_PON;
}
}
else
{
R8_HFCK_PWR_CTRL &= ~RB_CLK_XT32M_PON;
}
}
R8_SAFE_MODE_CTRL |= RB_SAFE_AUTO_EN;
sys_safe_access_disable();
}
/*********************************************************************
* @fn highcode_init
*
* @brief <EFBFBD><EFBFBD><EFBFBD><EFBFBD>highcode<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
*
* @param none
*
* @return none
*/
__attribute__((section(".highcode_init")))
void highcode_init(void)
{
R32_SAFE_MODE_CTRL |= RB_XROM_312M_SEL;
R8_SAFE_MODE_CTRL &= ~RB_SAFE_AUTO_EN;
sys_safe_access_enable();
R32_MISC_CTRL |= 5; //
R8_PLL_CONFIG &= ~(1 << 5); //
R8_HFCK_PWR_CTRL |= RB_CLK_RC16M_PON | RB_CLK_PLL_PON;
R16_CLK_SYS_CFG = CLK_SOURCE_HSI_PLL_62_4MHz;
R8_FLASH_CFG = 0X02;
R8_XT32M_TUNE = (R8_XT32M_TUNE&(~0x03))|0x01;
R8_SAFE_MODE_CTRL |= RB_SAFE_AUTO_EN;
sys_safe_access_disable();
}
/*********************************************************************
* @fn MachineMode_Call_IRQ
*
* @brief <EFBFBD><EFBFBD>еģʽ<EFBFBD><EFBFBD><EFBFBD>ú<EFBFBD><EFBFBD><EFBFBD>ʹ<EFBFBD>õ<EFBFBD><EFBFBD>ж<EFBFBD>
*
* @param none
*
* @return none
*/
__HIGH_CODE
__INTERRUPT
void MachineMode_Call_IRQ(void)
{
if(gs_machine_mode_func != NULL)
{
gs_machine_mode_func();
gs_machine_mode_func = NULL;
}
}
/*********************************************************************
* @fn MachineMode_Call
*
* @brief ע<EFBFBD><EFBFBD><EFBFBD><EFBFBD>еģʽִ<EFBFBD>к<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڻ<EFBFBD>еģʽ<EFBFBD>µ<EFBFBD><EFBFBD><EFBFBD>
*
* @param func - <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڻ<EFBFBD>еģʽ<EFBFBD><EFBFBD>ִ<EFBFBD>еĺ<EFBFBD><EFBFBD><EFBFBD>
*
* @return none
*/
__HIGH_CODE
void MachineMode_Call(MachineMode_Call_func func)
{
uint8_t i;
uint32_t sw_vtf, sw_irqtable;
uint32_t irqv;
/* <20><><EFBFBD><EFBFBD><EFBFBD>ر<EFBFBD><D8B1><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ж<EFBFBD> */
irqv = (PFIC->ISR[0] >> 8) | (PFIC->ISR[1] << 24);
PFIC->IRER[0] = 0xffffffff;
PFIC->IRER[1] = 0xffffffff;
/* <20><><EFBFBD><EFBFBD><EFBFBD>û<EFBFBD>ʹ<EFBFBD><CAB9><EFBFBD><EFBFBD>SW<53>жϵ<D0B6><CFB5><EFBFBD><EFBFBD><EFBFBD><EFBFBD>жϣ<D0B6><CFA3><EFBFBD><EFBFBD><EFBFBD>Ҫȡ<D2AA><C8A1><EFBFBD>˺<EFBFBD><CBBA><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ע<EFBFBD><D7A2> */
// for(i = 0; i < 4; i++)
// {
// if(PFIC->VTFIDR[i] == SWI_IRQn)
// {
// /* <20>ҵ<EFBFBD><D2B5><EFBFBD><EFBFBD>û<EFBFBD><C3BB>Լ<EFBFBD>ʹ<EFBFBD>õ<EFBFBD>SW<53>жϣ<D0B6><CFA3>ر<EFBFBD><D8B1><EFBFBD> */
// sw_vtf = PFIC->VTFADDR[i];
// PFIC->VTFADDR[i] = (sw_vtf & 0xFFFFFFFE);
// break;
// }
// }
sw_irqtable = _vector_base[SWI_IRQn];
_vector_base[SWI_IRQn] = (uint32_t)MachineMode_Call_IRQ;
gs_machine_mode_func = func;
/* ֻ<><D6BB><EFBFBD><EFBFBD>SWI_IRQn */
PFIC_EnableIRQ(SWI_IRQn);
/* <20><><EFBFBD><EFBFBD>SWI_IRQn<51>жϴ<D0B6><CFB4><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> */
PFIC_SetPendingIRQ(SWI_IRQn);
/* <20>ȴ<EFBFBD><C8B4><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> */
while(gs_machine_mode_func != NULL);
PFIC_DisableIRQ(SWI_IRQn);
// if(i != 4)
// {
// /* <20>ָ<EFBFBD>ԭ<EFBFBD><D4AD><EFBFBD><EFBFBD>SW<53><57><EFBFBD><EFBFBD><EFBFBD>ж<EFBFBD> */
// PFIC->VTFADDR[i] = sw_vtf;
// }
/* <20><><EFBFBD><EFBFBD><EFBFBD>ָ<EFBFBD>ԭ<EFBFBD><D4AD><EFBFBD><EFBFBD><EFBFBD>ж<EFBFBD>ʹ<EFBFBD><CAB9><EFBFBD><EFBFBD><EFBFBD><EFBFBD> */
PFIC->IENR[0] = (irqv << 8);
PFIC->IENR[1] = (irqv >> 24);
}
/*********************************************************************
* @fn SetPI_func
*
* @brief <EFBFBD><EFBFBD><EFBFBD>ڻ<EFBFBD>еģʽ<EFBFBD><EFBFBD><EFBFBD>õ<EFBFBD>ʹ<EFBFBD><EFBFBD>Ԥȡָ<EFBFBD><EFBFBD><EFBFBD>
*
* @param none
*
* @return none
*/void SetPI_func()
{
write_csr(0xbc0, 0x25);
}
/*********************************************************************
* @fn SYS_EnablePI
*
* @brief ʹ<EFBFBD><EFBFBD>Ԥȡָ<EFBFBD><EFBFBD><EFBFBD>
*
* @param none
*
* @return null
*/
void SYS_EnablePI()
{
MachineMode_Call(SetPI_func);
}
/*********************************************************************
* @fn GetSysClock
*
* @brief <EFBFBD><EFBFBD>ȡ<EFBFBD><EFBFBD>ǰϵͳʱ<EFBFBD><EFBFBD>
*
* @param none
*
* @return Hz
*/
uint32_t GetSysClock(void)
{
if((R16_CLK_SYS_CFG & RB_CLK_SYS_MOD) == RB_CLK_SYS_MOD)
{ // 32K<32><4B><EFBFBD><EFBFBD>Ƶ
return (CAB_LSIFQ);
}
else if(R16_CLK_SYS_CFG & RB_XROM_SCLK_SEL)
{
if(!(R16_CLK_SYS_CFG & 0x1f))
{
return ((R16_CLK_SYS_CFG & RB_OSC32M_SEL)?32000000:16000000);
}
else
{ // PLL<4C><4C><EFBFBD>з<EFBFBD>Ƶ
return (312000000 / (R16_CLK_SYS_CFG & 0x1f));
}
}
else if(R16_CLK_SYS_CFG & RB_OSC32M_SEL)
{ // 32M<32><4D><EFBFBD>з<EFBFBD>Ƶ
return (32000000 / (R16_CLK_SYS_CFG & 0x1f));
}
else
{ // 16M<36><4D><EFBFBD>з<EFBFBD>Ƶ
return (16000000 / (R16_CLK_SYS_CFG & 0x1f));
}
}
/*********************************************************************
* @fn SYS_GetInfoSta
*
* @brief <EFBFBD><EFBFBD>ȡ<EFBFBD><EFBFBD>ǰϵͳ<EFBFBD><EFBFBD>Ϣ״̬
*
* @param i - refer to SYS_InfoStaTypeDef
*
* @return <EFBFBD>Ƿ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
*/
uint8_t SYS_GetInfoSta(SYS_InfoStaTypeDef i)
{
if(i == STA_SAFEACC_ACT)
{
return (R8_SAFE_ACCESS_SIG & RB_SAFE_ACC_ACT);
}
else
{
return (R8_GLOB_CFG_INFO & (1 << i));
}
}
/*********************************************************************
* @fn SYS_ResetExecute
*
* @brief ִ<EFBFBD><EFBFBD>ϵͳ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>λ
*
* @param none
*
* @return none
*/
__HIGH_CODE
void SYS_ResetExecute(void)
{
FLASH_ROM_SW_RESET();
sys_safe_access_enable();
R8_RST_WDOG_CTRL |= RB_SOFTWARE_RESET;
sys_safe_access_disable();
}
/*********************************************************************
* @fn SYS_DisableAllIrq
*
* @brief <EFBFBD>ر<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>жϣ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ǰ<EFBFBD>ж<EFBFBD>ֵ
*
* @param pirqv - <EFBFBD><EFBFBD>ǰ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ж<EFBFBD>ֵ
*
* @return none
*/
void SYS_DisableAllIrq(uint32_t *pirqv)
{
*pirqv = (PFIC->ISR[0] >> 8) | (PFIC->ISR[1] << 24);
PFIC->IRER[0] = 0xffffffff;
PFIC->IRER[1] = 0xffffffff;
}
/*********************************************************************
* @fn SYS_RecoverIrq
*
* @brief <EFBFBD>ָ<EFBFBD>֮ǰ<EFBFBD>رյ<EFBFBD><EFBFBD>ж<EFBFBD>ֵ
*
* @param irq_status - <EFBFBD><EFBFBD>ǰ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ж<EFBFBD>ֵ
*
* @return none
*/
void SYS_RecoverIrq(uint32_t irq_status)
{
PFIC->IENR[0] = (irq_status << 8);
PFIC->IENR[1] = (irq_status >> 24);
}
/*********************************************************************
* @fn SYS_GetSysTickCnt
*
* @brief <EFBFBD><EFBFBD>ȡ<EFBFBD><EFBFBD>ǰϵͳ(SYSTICK)<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֵ
*
* @param none
*
* @return <EFBFBD><EFBFBD>ǰ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֵ
*/
uint32_t SYS_GetSysTickCnt(void)
{
return SysTick->CNTL;
}
/*********************************************************************
* @fn WWDG_ITCfg
*
* @brief <EFBFBD><EFBFBD><EFBFBD>Ź<EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ж<EFBFBD>ʹ<EFBFBD><EFBFBD>
*
* @param s - <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ƿ<EFBFBD><EFBFBD>ж<EFBFBD>
*
* @return none
*/
void WWDG_ITCfg(FunctionalState s)
{
uint8_t ctrl = R8_RST_WDOG_CTRL;
if(s == DISABLE)
{
ctrl &= ~RB_WDOG_INT_EN;
}
else
{
ctrl |= RB_WDOG_INT_EN;
}
sys_safe_access_enable();
R8_RST_WDOG_CTRL = ctrl;
sys_safe_access_disable();
}
/*********************************************************************
* @fn WWDG_ResetCfg
*
* @brief <EFBFBD><EFBFBD><EFBFBD>Ź<EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>λ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
*
* @param s - <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ƿ<EFBFBD><EFBFBD><EFBFBD>λ
*
* @return none
*/
void WWDG_ResetCfg(FunctionalState s)
{
uint8_t ctrl = R8_RST_WDOG_CTRL;
if(s == DISABLE)
{
ctrl &= ~RB_WDOG_RST_EN;
}
else
{
ctrl |= RB_WDOG_RST_EN;
}
sys_safe_access_enable();
R8_RST_WDOG_CTRL = ctrl;
sys_safe_access_disable();
}
/*********************************************************************
* @fn WWDG_ClearFlag
*
* @brief <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ź<EFBFBD><EFBFBD>жϱ<EFBFBD>־<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>¼<EFBFBD><EFBFBD>ؼ<EFBFBD><EFBFBD><EFBFBD>ֵҲ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
*
* @param none
*
* @return none
*/
void WWDG_ClearFlag(void)
{
sys_safe_access_enable();
R8_RST_WDOG_CTRL |= RB_WDOG_INT_FLAG;
sys_safe_access_disable();
}
/*********************************************************************
* @fn HardFault_Handler
*
* @brief Ӳ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>жϣ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ִ<EFBFBD>и<EFBFBD>λ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>λ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊ<EFBFBD>ϵλ
*
* @param none
*
* @return none
*/
__INTERRUPT
__HIGH_CODE
__attribute__((weak))
void HardFault_Handler(void)
{
2024-12-11 20:03:50 +08:00
uint32_t v_mepc,v_mcause,v_mtval;
v_mepc=__get_MEPC();
v_mcause=__get_MCAUSE();
v_mtval=__get_MTVAL();
printf("hardfault\n");
printf("mepc:%08x\n",v_mepc);
printf("mcause:%08x\n",v_mcause);
printf("mtval:%08x\n",v_mtval);
2024-12-03 11:11:30 +08:00
FLASH_ROM_SW_RESET();
sys_safe_access_enable();
R16_INT32K_TUNE = 0xFFFF;
sys_safe_access_disable();
sys_safe_access_enable();
R8_RST_WDOG_CTRL |= RB_SOFTWARE_RESET;
sys_safe_access_disable();
2024-12-11 20:03:50 +08:00
2024-12-03 11:11:30 +08:00
while(1);
}
/*********************************************************************
* @fn mDelayuS
*
* @brief uS <EFBFBD><EFBFBD>ʱ
*
* @param t - ʱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
*
* @return none
*/
__HIGH_CODE
void mDelayuS(uint16_t t)
{
uint32_t i;
#if(FREQ_SYS == 78000000)
i = t * 13;
#elif(FREQ_SYS == 62400000)
i = ((uint32_t)t * 78) / 5;
#elif(FREQ_SYS == 52000000)
i = t * 13;
#elif(FREQ_SYS == 39000000)
i = (t * 13)>>1;
#elif(FREQ_SYS == 26000000)
i = (t * 13)>>1;
#elif(FREQ_SYS == 24000000)
i = t * 6;
#elif(FREQ_SYS == 19500000)
i = (t * 13)>>2;
#elif(FREQ_SYS == 32000000)
i = t << 3;
#elif(FREQ_SYS == 16000000)
i = t << 2;
#elif(FREQ_SYS == 13000000)
i = (t * 13)>>2;
#elif(FREQ_SYS == 8000000)
i = t << 1;
#elif(FREQ_SYS == 4000000)
i = t;
#elif(FREQ_SYS == 2000000)
i = t >> 1;
#elif(FREQ_SYS == 1000000)
i = t >> 2;
#else
i = t;
#endif
#if((FREQ_SYS == 78000000)||\
(FREQ_SYS == 39000000)||\
(FREQ_SYS == 19500000))
while(--i)
{
__nop();
};
#else
do
{
__nop();
}while(--i);
#endif
}
/*********************************************************************
* @fn mDelaymS
*
* @brief mS <EFBFBD><EFBFBD>ʱ
*
* @param t - ʱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
*
* @return none
*/
__HIGH_CODE
void mDelaymS(uint16_t t)
{
do
{
mDelayuS(1000);
}while(--t);
}
#ifdef DEBUG
int _write(int fd, char *buf, int size)
{
2024-12-07 17:09:36 +08:00
BSP_Uart3_Send_Data(buf, size);
// int i;
// for(i = 0; i < size; i++)
// {
//#if DEBUG == Debug_UART0
// while(R8_UART0_TFC == UART_FIFO_SIZE); /* <20>ȴ<EFBFBD><C8B4><EFBFBD><EFBFBD>ݷ<EFBFBD><DDB7><EFBFBD> */
// R8_UART0_THR = *buf++; /* <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> */
//#elif DEBUG == Debug_UART1
// while(R8_UART1_TFC == UART_FIFO_SIZE); /* <20>ȴ<EFBFBD><C8B4><EFBFBD><EFBFBD>ݷ<EFBFBD><DDB7><EFBFBD> */
// R8_UART1_THR = *buf++; /* <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> */
//#elif DEBUG == Debug_UART2
// while(R8_UART2_TFC == UART_FIFO_SIZE); /* <20>ȴ<EFBFBD><C8B4><EFBFBD><EFBFBD>ݷ<EFBFBD><DDB7><EFBFBD> */
// R8_UART2_THR = *buf++; /* <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> */
//#elif DEBUG == Debug_UART3
// while(R8_UART3_TFC == UART_FIFO_SIZE); /* <20>ȴ<EFBFBD><C8B4><EFBFBD><EFBFBD>ݷ<EFBFBD><DDB7><EFBFBD> */
// R8_UART3_THR = *buf++; /* <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> */
//#endif
// }
2024-12-03 11:11:30 +08:00
return size;
}
#endif
/*********************************************************************
* @fn _sbrk
*
* @brief Change the spatial position of data segment.
*
* @return size: Data length
*/
__attribute__((used))
void *_sbrk(ptrdiff_t incr)
{
extern char _end[];
static char *curbrk = _end;
if ((curbrk + incr < _end) || ((uint32_t)curbrk + incr > (__get_SP() - 64)))
return NULL - 1;
curbrk += incr;
return curbrk - incr;
}
/*********************************************************************
* @fn __wrap_memcpy
*
* @brief wrap memcpy
*
* @return dst
*/
__HIGH_CODE
void *__wrap_memcpy(void *dst, void *src, size_t size)
{
__MCPY(dst, src, (void *)((uint32_t)src+size));
return dst;
}