gpio.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618
  1. /**
  2. * @file gpio.c
  3. * @author chipsea
  4. * @brief Contains all functions support for gpio and iomux driver
  5. * @version 0.1
  6. * @date 2020-11-30
  7. * @copyright Copyright (c) 2020, CHIPSEA Co., Ltd.
  8. * @note
  9. */
  10. #include "sdk_config.h"
  11. #include "log.h"
  12. #include "mcu.h"
  13. #include "gpio.h"
  14. #include "types.h"
  15. #include "clock.h"
  16. #include "error.h"
  17. #include "string.h"
  18. #include "pwrmgr.h"
  19. #include "jump_function.h"
  20. extern uint32_t s_gpio_wakeup_src_group1, s_gpio_wakeup_src_group2;
  21. enum {
  22. GPIO_PIN_ASSI_NONE = 0,
  23. GPIO_PIN_ASSI_OUT,
  24. GPIO_PIN_ASSI_IN,
  25. };
  26. typedef struct {
  27. bool enable;
  28. uint8_t pin_state;
  29. gpioin_Hdl_t posedgeHdl;
  30. gpioin_Hdl_t negedgeHdl;
  31. }gpioin_Ctx_t;
  32. typedef struct {
  33. bool state;
  34. uint8_t pin_assignments[NUMBER_OF_PINS];
  35. gpioin_Ctx_t irq_ctx[NUMBER_OF_PINS];
  36. }gpio_Ctx_t;
  37. typedef struct{
  38. uint8_t reg_i;
  39. uint8_t bit_h;
  40. uint8_t bit_l;
  41. }PULL_TypeDef;
  42. static gpio_Ctx_t m_gpioCtx = {
  43. .state = FALSE,
  44. .pin_assignments = {0,},
  45. };
  46. const uint8_t c_gpio_index[GPIO_NUM] = {0,1,2,3,7,9,10,11,14,15,16,17,18,20,23,24,25,26,27,31,32,33,34};
  47. const PULL_TypeDef c_gpio_pull[GPIO_NUM]=
  48. {
  49. {0,2,1}, //p0
  50. {0,5,4}, //p1
  51. {0,8,7}, //p2
  52. {0,11,10},//p3
  53. {0,23,22},//p7
  54. {0,29,28},//p9
  55. {1,2,1}, //p10
  56. {1,5,4}, //p11
  57. {1,14,13},//p14
  58. {1,17,16},//p15
  59. {1,20,19},//p16
  60. {1,23,22},//p17
  61. {1,26,25},//p18
  62. {2,2,1}, //p20
  63. {2,11,10},//p23
  64. {2,14,13},//p24
  65. {2,17,16},//p25
  66. {2,20,19},//p26
  67. {2,23,22},//p27
  68. {3,5,4}, //p31
  69. {3,8,7}, //p32
  70. {3,11,10},//p33
  71. {3,14,13},//p34
  72. };
  73. const signed char retention_reg[GPIO_NUM][2]={
  74. {0,13},//p0
  75. {0,14},//p1
  76. {0,16},//p2
  77. {0,17},//p3
  78. {0,19},//p7
  79. {0,20},//p9
  80. {1,7},//p10
  81. {1,8},//p11
  82. {1,10},//p14
  83. {1,11},//p15
  84. {1,28},//p16
  85. {1,29},//p17
  86. {2,4},//p18
  87. {2,5},//p20
  88. {2,7},//p23
  89. {2,8},//p24
  90. {2,25},//p25
  91. {2,26},//p26
  92. {2,28},//p27
  93. {2,29},//p31
  94. {3,1},//p32
  95. {3,2},//p33
  96. {3,23},//p34
  97. };
  98. static int hal_gpio_interrupt_disable(GpioPin_t pin)
  99. {
  100. subWriteReg(&(AP_GPIO->intmask),pin,pin,1);
  101. subWriteReg(&(AP_GPIO->inten),pin,pin,0);
  102. return ERR_NONE;
  103. }
  104. static void hal_gpio_wakeup_control(GpioPin_t pin, bit_action_e value)
  105. {
  106. if(pin < P32)
  107. {
  108. if (value)
  109. AP_AON->REG_S9 |= BIT(c_gpio_index[pin]);
  110. else
  111. AP_AON->REG_S9 &= ~BIT(c_gpio_index[pin]);
  112. }
  113. else
  114. {
  115. if (value)
  116. AP_AON->REG_S10 |= BIT(c_gpio_index[pin] - 32);
  117. else
  118. AP_AON->REG_S10 &= ~BIT(c_gpio_index[pin] - 32);
  119. }
  120. }
  121. void HalGpioDsControl(GpioPin_t pin, bit_action_e value)
  122. {
  123. if(value)
  124. AP_IOMUX->pad_ps0 |= BIT(pin);
  125. else
  126. AP_IOMUX->pad_ps0 &= ~BIT(pin);
  127. }
  128. ErrCode_t HalGpioAnalogConfig(GpioPin_t pin, bit_action_e value)
  129. {
  130. if((pin < P11) || (pin > P25))
  131. return ERR_INVALID_PARAM;
  132. if(value > Bit_ENABLE)
  133. {
  134. return ERR_INVALID_DATA;
  135. }
  136. if(value)
  137. {
  138. HalGpioPupdConfig(pin,GPIO_FLOATING);
  139. AP_IOMUX->Analog_IO_en |= BIT(pin - P11);
  140. }
  141. else
  142. {
  143. AP_IOMUX->Analog_IO_en &= ~BIT(pin - P11);
  144. }
  145. return ERR_NONE;
  146. }
  147. void HalGpioPin2Pin3Control(GpioPin_t pin, uint8_t en)//0:sw,1:other func
  148. {
  149. if(en)
  150. AP_IOMUX->gpio_pad_en |= BIT(pin-2);
  151. else
  152. AP_IOMUX->gpio_pad_en &= ~BIT(pin-2);
  153. }
  154. static void hal_gpio_retention_enable(GpioPin_t pin,uint8_t en)
  155. {
  156. if(en)
  157. {
  158. if((pin == P32)||(pin == P33)||(pin == P34))
  159. {
  160. AP_AON->PMCTL0 |= BIT(retention_reg[pin][1]);
  161. }
  162. else
  163. {
  164. AP_AON->IOCTL[retention_reg[pin][0]] |= BIT(retention_reg[pin][1]);
  165. }
  166. }
  167. else
  168. {
  169. if((pin == P32)||(pin == P33)||(pin == P34))
  170. {
  171. AP_AON->PMCTL0 &= ~BIT(retention_reg[pin][1]);
  172. }
  173. else
  174. {
  175. AP_AON->IOCTL[retention_reg[pin][0]] &= ~BIT(retention_reg[pin][1]);
  176. }
  177. }
  178. }
  179. int hal_gpioin_disable(GpioPin_t pin)
  180. {
  181. gpioin_Ctx_t* p_irq_ctx = &(m_gpioCtx.irq_ctx[0]);
  182. if (pin > (NUMBER_OF_PINS - 1))
  183. return ERR_NOT_SUPPORTED;
  184. p_irq_ctx[pin].enable = FALSE;
  185. m_gpioCtx.pin_assignments[pin] = GPIO_PIN_ASSI_NONE;
  186. HalGpioPinInit(pin, GPIO_INPUT);
  187. return hal_gpio_interrupt_disable(pin);
  188. }
  189. __ATTR_SECTION_SRAM__ static int hal_gpio_interrupt_enable(GpioPin_t pin, gpio_polarity_e type)
  190. {
  191. uint32_t gpio_tmp;
  192. if (pin >= NUMBER_OF_PINS)
  193. return ERR_NOT_SUPPORTED;
  194. gpio_tmp = AP_GPIO->inttype_level;
  195. gpio_tmp |= (1 << pin); //edge sensitive
  196. AP_GPIO->inttype_level = gpio_tmp;
  197. gpio_tmp = AP_GPIO->intmask;
  198. gpio_tmp &= ~(1 << pin); //unmask interrupt
  199. AP_GPIO->intmask = gpio_tmp;
  200. gpio_tmp = AP_GPIO->int_polarity;
  201. if (type == POL_RISING )
  202. gpio_tmp |= (1 << pin);
  203. else
  204. gpio_tmp &= ~(1 << pin);
  205. AP_GPIO->int_polarity = gpio_tmp;
  206. gpio_tmp = AP_GPIO->inten;
  207. gpio_tmp |= (1 << pin); //enable interrupt
  208. AP_GPIO->inten = gpio_tmp;
  209. return ERR_NONE;
  210. }
  211. __ATTR_SECTION_SRAM__ static void hal_gpioin_event_pin(GpioPin_t pin, gpio_polarity_e type)
  212. {
  213. gpioin_Ctx_t* p_irq_ctx = &(m_gpioCtx.irq_ctx[0]);
  214. if (p_irq_ctx[pin].posedgeHdl && (type == POL_RISING ))
  215. {
  216. p_irq_ctx[pin].posedgeHdl(pin,POL_RISING );//LOG("POS\n");
  217. }
  218. else if (p_irq_ctx[pin].negedgeHdl && (type == POL_FALLING))
  219. {
  220. p_irq_ctx[pin].negedgeHdl(pin,POL_FALLING);//LOG("NEG\n");
  221. }
  222. }
  223. static void hal_gpioin_wakeup_trigger(GpioPin_t pin)
  224. {
  225. uint8_t pin_state = (uint8_t)HalGpioGet(pin);
  226. gpio_polarity_e type = pin_state ? POL_RISING : POL_FALLING;
  227. if (m_gpioCtx.irq_ctx[pin].pin_state != pin_state)
  228. hal_gpioin_event_pin(pin, type);
  229. }
  230. __ATTR_SECTION_SRAM__ static void hal_gpioin_event(uint32 int_status, uint32 polarity)
  231. {
  232. int i;
  233. gpioin_Ctx_t* p_irq_ctx = &(m_gpioCtx.irq_ctx[0]);
  234. // LOG("GI:%x,%x\n",int_status,polarity);
  235. for (i = 0; i < NUMBER_OF_PINS; i++)
  236. {
  237. if (int_status & (1ul << i))
  238. {
  239. gpio_polarity_e type = (polarity & BIT(i)) ? POL_RISING : POL_FALLING;
  240. hal_gpioin_event_pin((GpioPin_t)i, type);
  241. //reconfig interrupt
  242. if (p_irq_ctx[i].posedgeHdl && p_irq_ctx[i].negedgeHdl) //both raise and fall
  243. {
  244. type = (type == POL_RISING) ? POL_FALLING : POL_RISING ;
  245. hal_gpio_interrupt_enable((GpioPin_t)i, type);
  246. }
  247. else if (p_irq_ctx[i].posedgeHdl) //raise
  248. {
  249. hal_gpio_interrupt_enable((GpioPin_t)i, POL_RISING );
  250. }
  251. else if (p_irq_ctx[i].negedgeHdl) //fall
  252. {
  253. hal_gpio_interrupt_enable((GpioPin_t)i, POL_FALLING);
  254. }
  255. }
  256. }
  257. }
  258. ErrCode_t hal_gpioin_enable(GpioPin_t pin)
  259. {
  260. gpioin_Ctx_t* p_irq_ctx = &(m_gpioCtx.irq_ctx[0]);
  261. gpio_polarity_e type = POL_FALLING;
  262. uint32 pinVal = 0;
  263. if (p_irq_ctx[pin].posedgeHdl == NULL && p_irq_ctx[pin].negedgeHdl == NULL)
  264. return ERR_NOT_REGISTED;
  265. m_gpioCtx.pin_assignments[pin] = GPIO_PIN_ASSI_IN;
  266. p_irq_ctx[pin].enable = TRUE;
  267. HalGpioPinInit(pin, GPIO_INPUT);
  268. //HalGpioPupdConfig(pin, PULL_DOWN); //??need disccuss
  269. if (p_irq_ctx[pin].posedgeHdl && p_irq_ctx[pin].negedgeHdl) //both raise and fall
  270. {
  271. pinVal = HalGpioGet(pin);
  272. type = pinVal ? POL_FALLING : POL_RISING ;
  273. }
  274. else if (p_irq_ctx[pin].posedgeHdl) //raise
  275. {
  276. type = POL_RISING ;
  277. }
  278. else if (p_irq_ctx[pin].negedgeHdl) //fall
  279. {
  280. type = POL_FALLING;
  281. }
  282. hal_gpio_interrupt_enable(pin, type);
  283. return ERR_NONE;
  284. }
  285. void GpioSleepHandler(void)
  286. {
  287. int i;
  288. gpio_polarity_e pol;
  289. uint8_t ic_ver = get_ic_version();
  290. for (i = 0; i < NUMBER_OF_PINS; i++)
  291. {
  292. //config wakeup
  293. if (m_gpioCtx.pin_assignments[i] == GPIO_PIN_ASSI_OUT)
  294. {
  295. hal_gpio_retention_enable((GpioPin_t)i,Bit_ENABLE);
  296. }
  297. if (m_gpioCtx.pin_assignments[i] == GPIO_PIN_ASSI_IN)
  298. {
  299. if(ic_ver != VERSION_0100 && ((i==P16)||(i==P17)))
  300. {
  301. HalGpioAnalogConfig((GpioPin_t)i,Bit_DISABLE);
  302. subWriteReg(&(AP_AON->PMCTL2_0),6,6,0x01);
  303. WaitUs(50);
  304. pol = HalGpioGet((GpioPin_t)i) ? POL_FALLING : POL_RISING ;
  305. subWriteReg(&(AP_AON->PMCTL2_0),6,6,0x00);
  306. }
  307. else
  308. {
  309. pol = HalGpioGet((GpioPin_t)i) ? POL_FALLING : POL_RISING ;
  310. }
  311. HalGpioWkupConfig((GpioPin_t)i, pol);
  312. m_gpioCtx.irq_ctx[i].pin_state = HalGpioGet((GpioPin_t)i);
  313. }
  314. }
  315. }
  316. void GpioWakeupHandler(void)
  317. {
  318. int i;
  319. uint8_t ic_ver = get_ic_version();
  320. NVIC_SetPriority(GPIO_IRQn, IRQ_PRIO_HAL);
  321. NVIC_EnableIRQ(GPIO_IRQn);
  322. for (i = 0; i < NUMBER_OF_PINS; i++)
  323. {
  324. if( ((i == GPIO_P02) || (i == GPIO_P03)) && (m_gpioCtx.pin_assignments[i] != GPIO_PIN_ASSI_NONE) )
  325. {
  326. HalGpioPin2Pin3Control((GpioPin_t)i,1);
  327. }
  328. if(ic_ver != VERSION_0100 && ((i==P16)||(i==P17)))
  329. {
  330. HalGpioAnalogConfig((GpioPin_t)i,Bit_DISABLE);
  331. }
  332. if (m_gpioCtx.pin_assignments[i] == GPIO_PIN_ASSI_OUT)
  333. {
  334. bool pol = HalGpioGet((GpioPin_t)i);
  335. HalGpioSet((GpioPin_t)i, (bit_action_e)pol);
  336. HalGpioPinInit((GpioPin_t)i, GPIO_OUTPUT);
  337. hal_gpio_retention_enable((GpioPin_t)i, Bit_DISABLE);
  338. }
  339. }
  340. for (i = 0; i < NUMBER_OF_PINS; i++)
  341. {
  342. if (m_gpioCtx.irq_ctx[i].enable)
  343. {
  344. hal_gpioin_enable((GpioPin_t)i); //resume gpio irq
  345. hal_gpioin_wakeup_trigger((GpioPin_t)i);//trigger gpio irq manually
  346. }
  347. }
  348. }
  349. __ATTR_SECTION_SRAM__ void HalGpioIRQHandler(void)
  350. {
  351. uint32 polarity = AP_GPIO->int_polarity;
  352. uint32 st = AP_GPIO->int_status;
  353. AP_GPIO->porta_eoi = st;//clear interrupt
  354. hal_gpioin_event(st, polarity);
  355. }
  356. bool HalBootPinStatusGet(void)
  357. {
  358. bool status;
  359. uint32_t config;
  360. config = *(volatile unsigned int *)0x4000f058;
  361. status = (config & 0x40)>> 6;
  362. return status;
  363. }
  364. void HalGpioSet(GpioPin_t pin, bit_action_e bitVal)
  365. {
  366. if(bitVal)
  367. AP_GPIO->swporta_dr |= BIT(pin);
  368. else
  369. AP_GPIO->swporta_dr &= ~BIT(pin);
  370. }
  371. bool HalGpioGet(GpioPin_t pin)
  372. {
  373. uint32_t r;
  374. if(pin >= GPIO_NUM )
  375. {
  376. return ERR_NOT_SUPPORTED;
  377. }
  378. if(AP_GPIO->swporta_ddr & BIT(pin))
  379. {
  380. r = AP_GPIO->swporta_dr;
  381. }
  382. else
  383. {
  384. r = AP_GPIO->ext_porta;
  385. }
  386. return (int)((r>> pin) &1);
  387. }
  388. ErrCode_t HalGpioPupdConfig(GpioPin_t pin, gpio_pupd_e type)
  389. {
  390. if(pin >= GPIO_NUM || type > GPIO_PULL_DOWN)
  391. {
  392. return ERR_NOT_SUPPORTED;
  393. }
  394. uint8_t i = c_gpio_pull[pin].reg_i;
  395. uint8_t h = c_gpio_pull[pin].bit_h;
  396. uint8_t l = c_gpio_pull[pin].bit_l;
  397. if(pin < P31)
  398. subWriteReg(&(AP_AON->IOCTL[i]),h,l,type);
  399. else
  400. subWriteReg(&(AP_AON->PMCTL0),h,l,type);
  401. return ERR_NONE;
  402. }
  403. ErrCode_t HalGpioFmuxEnable(GpioPin_t pin, bit_action_e value)
  404. {
  405. if(pin >= GPIO_NUM || value > Bit_ENABLE)
  406. {
  407. return ERR_NOT_SUPPORTED;
  408. }
  409. if(value)
  410. {
  411. AP_IOMUX->full_mux0_en |= BIT(pin);
  412. }
  413. else
  414. {
  415. AP_IOMUX->full_mux0_en &= ~BIT(pin);
  416. }
  417. return ERR_NONE;
  418. }
  419. ErrCode_t HalGpioFmuxConfig(GpioPin_t pin, gpio_fmux_e type)
  420. {
  421. uint8_t h = 0, l = 0;
  422. uint32_t reg_index;
  423. uint32_t bit_index;
  424. if( (pin >= GPIO_NUM) || (type > FMUX_ANT_SEL_2) )
  425. {
  426. return ERR_NOT_SUPPORTED;
  427. }
  428. reg_index = pin / 4;
  429. bit_index = pin % 4;
  430. l = 8 * bit_index;
  431. h = l + 5;
  432. subWriteReg(&(AP_IOMUX->gpio_sel[reg_index]),h,l,type);
  433. HalGpioFmuxEnable(pin, Bit_ENABLE);
  434. return ERR_NONE;
  435. }
  436. ErrCode_t HalGpioWkupConfig(GpioPin_t pin, gpio_polarity_e type)
  437. {
  438. if(pin >= GPIO_NUM || type > POL_RISING)
  439. {
  440. return ERR_NOT_SUPPORTED;
  441. }
  442. uint8_t i = c_gpio_pull[pin].reg_i;
  443. uint8_t p = c_gpio_pull[pin].bit_l-1;
  444. if (m_gpioCtx.pin_assignments[pin] != GPIO_PIN_ASSI_IN)
  445. return ERR_INVALID_STATE;
  446. AP_GPIO->inttype_level |= BIT(pin);//edge sensitive
  447. if(pin < P31)
  448. {
  449. if(POL_FALLING == type)
  450. AP_AON->IOCTL[i] |= BIT(p);
  451. else
  452. AP_AON->IOCTL[i] &= ~BIT(p);
  453. }
  454. else
  455. {
  456. if(POL_FALLING == type)
  457. AP_AON->PMCTL0 |= BIT(p);
  458. else
  459. AP_AON->PMCTL0 &= ~BIT(p);
  460. }
  461. hal_gpio_wakeup_control(pin,Bit_ENABLE);//enable wakeup function
  462. return ERR_NONE;
  463. }
  464. ErrCode_t HalGpioRegister(GpioPin_t pin, gpioin_Hdl_t posedgeHdl, gpioin_Hdl_t negedgeHdl)
  465. {
  466. ErrCode_t ret;
  467. gpioin_Ctx_t* p_irq_ctx = &(m_gpioCtx.irq_ctx[0]);
  468. if(pin >= GPIO_NUM )
  469. {
  470. return ERR_NOT_SUPPORTED;
  471. }
  472. hal_gpioin_disable(pin);
  473. p_irq_ctx[pin].posedgeHdl = posedgeHdl;
  474. p_irq_ctx[pin].negedgeHdl = negedgeHdl;
  475. ret = hal_gpioin_enable(pin);
  476. JUMP_FUNCTION(V16_IRQ_HANDLER) = (uint32_t)&HalGpioIRQHandler;
  477. if (ret != ERR_NONE)
  478. hal_gpioin_disable(pin);
  479. return ret;
  480. }
  481. ErrCode_t HalGpioUnregister(GpioPin_t pin)
  482. {
  483. gpioin_Ctx_t* p_irq_ctx = &(m_gpioCtx.irq_ctx[0]);
  484. if (pin >= GPIO_NUM)
  485. return ERR_NOT_SUPPORTED;
  486. hal_gpioin_disable(pin);
  487. p_irq_ctx[pin].negedgeHdl = NULL;
  488. p_irq_ctx[pin].posedgeHdl = NULL;
  489. return ERR_NONE;
  490. }
  491. ErrCode_t HalGpioInit(void)
  492. {
  493. if (m_gpioCtx.state)
  494. return ERR_INVALID_STATE;
  495. memset(&m_gpioCtx, 0, sizeof(m_gpioCtx));
  496. m_gpioCtx.state = TRUE;
  497. //disable all channel irq,unmask all channel
  498. AP_GPIO->inten = 0;
  499. AP_GPIO->intmask = 0;
  500. //disable all wakeup pin
  501. AP_WAKEUP->io_wu_mask_31_0 = 0;
  502. AP_WAKEUP->io_wu_mask_34_32 = 0;
  503. NVIC_SetPriority(GPIO_IRQn, IRQ_PRIO_HAL);
  504. NVIC_EnableIRQ(GPIO_IRQn);
  505. hal_pwrmgr_register(MOD_GPIO, GpioSleepHandler, GpioWakeupHandler);
  506. return ERR_NONE;
  507. }
  508. ErrCode_t HalGpioPinInit(GpioPin_t pin, gpio_dir_t type)
  509. {
  510. if(pin >= GPIO_NUM || type > GPIO_OUTPUT)
  511. {
  512. return ERR_NOT_SUPPORTED;
  513. }
  514. HalGpioFmuxEnable(pin,Bit_DISABLE);
  515. if((pin == P2) || (pin == P3))
  516. HalGpioPin2Pin3Control(pin,1);
  517. HalGpioAnalogConfig(pin,Bit_DISABLE);
  518. if(type == GPIO_OUTPUT)
  519. {
  520. AP_GPIO->swporta_ddr |= BIT(pin);
  521. m_gpioCtx.pin_assignments[pin] = GPIO_PIN_ASSI_OUT;
  522. }
  523. else
  524. {
  525. AP_GPIO->swporta_ddr &= ~BIT(pin);
  526. m_gpioCtx.pin_assignments[pin] = GPIO_PIN_ASSI_IN;
  527. }
  528. return ERR_NONE;
  529. }