388 lines
13 KiB
Plaintext
388 lines
13 KiB
Plaintext
; --------------------------------------------------------------------------------
|
|
; @Title: Serial fLash script for for IMXRT685-CM33 on IMXRT685-EVK
|
|
; @Description:
|
|
;
|
|
; The MX25UM51345(MXIC) Octal DDR flash memory is on the FlexSPI0B_SS0. (NOT A)
|
|
;
|
|
; SRAM: 0x20001000
|
|
; FlexSPI Controller Base: 0x40134000
|
|
; FlexSPI memory mapped ADDRESS: 0x08000000
|
|
;
|
|
; PIO1_11 -- FLEXSPI0B_DATA0 OctalSPI Flash
|
|
; PIO1_12 -- FLEXSPI0B_DATA1 OctalSPI Flash
|
|
; PIO1_13 -- FLEXSPI0B_DATA2 OctalSPI Flash
|
|
; PIO1_14 -- FLEXSPI0B_DATA3 OctalSPI Flash
|
|
; PIO1_29 -- FLEXSPI0B_SCLK OctalSPI Flash
|
|
; PIO2_12 -- PIO2_12 RESET OctalSPI Flash
|
|
; PIO2_17 -- FLEXSPI0B_DATA4 OctalSPI Flash
|
|
; PIO2_18 -- FLEXSPI0B_DATA5 OctalSPI Flash
|
|
; PIO2_19 -- FLEXSPI0B_SS0_N OctalSPI Flash
|
|
; PIO2_22 -- FLEXSPI0B_DATA6 OctalSPI Flash
|
|
; PIO2_23 -- FLEXSPI0B_DATA7 OctalSPI Flash
|
|
;
|
|
; Prerequisites:
|
|
; * Connect Combiprobe/uTrace to J19
|
|
; * Select FlexSPI boot mode on the EVB
|
|
; The ISP pins (PIO1_15, PIO3_28, and PIO3_29)
|
|
; SP[2:0] == 100 on the SW7, the documentation is opposite
|
|
;
|
|
; @Keywords: ARM, Cortex-M7, ITM, SWV, SPI, OPI, OCTAL, DDR
|
|
; @Author: JIM
|
|
; @Board: IMXRT685-EVK
|
|
; @Chip: IMXRT685-CM33
|
|
; @Copyright: (C) 1989-202s Lauterbach GmbH, licensed for use with TRACE32(R) only
|
|
; --------------------------------------------------------------------------------
|
|
; $Id: imxrt685-spi.cmm 12049 2023-04-20 12:32:16Z bschroefel $
|
|
|
|
&FLEXSPI_BASE=0x40134000 ;FLEXSPI0 controller base address
|
|
|
|
ENTRY %LINE ¶meters
|
|
¶m_prepareonly=(STRing.SCAN(STRing.UPpeR("¶meters"),"PREPAREONLY",0)!=-1)
|
|
|
|
; --------------------------------------------------------------------------------
|
|
; initialize and start the debugger
|
|
IF !SYStem.Up()
|
|
(
|
|
|
|
RESet
|
|
SYStem.CPU IMXRT685-CM33
|
|
IF COMBIPROBE()||UTRACE()
|
|
(
|
|
SYStem.CONFIG.CONNECTOR MIPI20T
|
|
)
|
|
;SYStem.Option.ResBreak ON ; it needs to drive the cold reset for QSPI boot
|
|
SYStem.Option DUALPORT ON
|
|
SYStem.MemAccess DAP
|
|
SYStem.JtagClock 10MHz
|
|
ETM.OFF
|
|
ITM.OFF
|
|
SYStem.Up
|
|
)
|
|
|
|
IF RUN()
|
|
Break
|
|
|
|
; ------------------------------------------------------------------------------
|
|
; Flash Controller Power & Clock Enable
|
|
GOSUB ClockInit
|
|
|
|
; ------------------------------------------------------------------------------
|
|
; Flash Pin Mux Configuration
|
|
GOSUB IOMUXconfig
|
|
|
|
; ------------------------------------------------------------------------------
|
|
; Flash Controller Init
|
|
GOSUB FLEXSPIconfig
|
|
|
|
; ------------------------------------------------------------------------------
|
|
; Flash Read ID Test
|
|
GOSUB READ_ID_TEST
|
|
|
|
; ------------------------------------------------------------------------------
|
|
; Init SRAM (16KB) for the flash algorithm
|
|
Data.Test 0x20001000++0x3FFF
|
|
|
|
; ------------------------------------------------------------------------------
|
|
; Flash declaration
|
|
Break.RESet
|
|
FLASH.RESet
|
|
FLASH.Create 0x08000000++0xFFFFFF 0x10000 TARGET Byte
|
|
FLASH.TARGET 0x20001000 E:0x20203000 0x4000 ~~/demo/arm/flash/byte/snor_imxrt500.bin /DUALPORT
|
|
|
|
; Flash script ends here if called with parameter PREPAREONLY
|
|
IF ¶m_prepareonly
|
|
ENDDO PREPAREDONE
|
|
|
|
; ------------------------------------------------------------------------------
|
|
; Flash programming example
|
|
|
|
DIALOG.YESNO "Program flash memory?"
|
|
LOCAL &progflash
|
|
ENTRY &progflash
|
|
IF &progflash
|
|
(
|
|
FLASH.ReProgram.ALL
|
|
Data.LOAD.auto *
|
|
;Data.LOAD.Binary * 0x08000000
|
|
FLASH.ReProgram.off
|
|
|
|
; Reset device
|
|
PRINT "Please power-cycle the board after flash program is complete"
|
|
)
|
|
|
|
ENDDO
|
|
; --------------------------------------------------------------------------------
|
|
|
|
ClockInit:
|
|
(
|
|
Data.Set ZSD:0x40002110 %LE %Long 0x0
|
|
Data.Set ZSD:0x40002604 %LE %Long 0x067FFFFF
|
|
Data.Set ZSD:0x40002614 %LE %Long 0x067FFFF3 ;PDSLEEPCFG1
|
|
Data.Set ZSD:0x40002684 %LE %Long 0x1<<10.
|
|
|
|
Data.Set ZSD:0x40001620 %LE %Long 0x00000000 ;clk sel, main clock for flexspi clk
|
|
Data.Set ZSD:0x40001624 %LE %Long 0x80000007 ;div 8
|
|
|
|
PER.Set.simple AZSD:0x40001010 %Long data.long(AZSD:0x40001010)|(0x1<<16.) ;enable
|
|
RETURN
|
|
)
|
|
|
|
FLEXSPIconfig:
|
|
(
|
|
//unlock
|
|
Data.Set A:&FLEXSPI_BASE+0x018 %LE %Long 0x5AF05AF0
|
|
Data.Set A:&FLEXSPI_BASE+0x01C %LE %Long 2
|
|
|
|
IF Data.Long(A:&FLEXSPI_BASE)==0xFFFFA030 ;current flash state is octal ddr
|
|
(
|
|
GOSUB RESET_Memory_OCTAL_DDR
|
|
Data.Set A:&FLEXSPI_BASE+0x000 %LE %Long 0xFFFF8101 ;SPI mode & div/2, and SW reset assert
|
|
)
|
|
|
|
//controller init
|
|
Data.Set A:&FLEXSPI_BASE+0x000 %LE %Long 0xFFFF8100
|
|
Data.Set A:&FLEXSPI_BASE+0x004 %LE %Long 0xFFFFFFFF
|
|
Data.Set A:&FLEXSPI_BASE+0x008 %LE %Long 0x200001F7
|
|
Data.Set A:&FLEXSPI_BASE+0x00C %LE %Long 0x58
|
|
Data.Set A:&FLEXSPI_BASE+0x010 %LE %Long 0xFFFFFFFF; interrupt enable
|
|
|
|
Data.Set A:&FLEXSPI_BASE+0x020 %LE %Long 0x80000000
|
|
Data.Set A:&FLEXSPI_BASE+0x024 %LE %Long 0x80000000
|
|
Data.Set A:&FLEXSPI_BASE+0x028 %LE %Long 0x80000000
|
|
Data.Set A:&FLEXSPI_BASE+0x060 %LE %Long 0x00200000
|
|
|
|
;Data.Set A:&FLEXSPI_BASE+0x000 %LE %Long 0xFFFFA030
|
|
|
|
Data.Set A:&FLEXSPI_BASE+0x004 %LE %Long 0xFFFFFFFF
|
|
Data.Set A:&FLEXSPI_BASE+0x008 %LE %Long 0x200001F7
|
|
Data.Set A:&FLEXSPI_BASE+0x00C %LE %Long 0x78
|
|
Data.Set A:&FLEXSPI_BASE+0x020 %LE %Long 0x80000000
|
|
Data.Set A:&FLEXSPI_BASE+0x024 %LE %Long 0x80000000
|
|
Data.Set A:&FLEXSPI_BASE+0x028 %LE %Long 0x80000000
|
|
//define FlexSPI0B_SS0 driving address to 0x08000000++0xFFFFFF
|
|
Data.Set A:&FLEXSPI_BASE+0x060 %LE %Long 0x00000000 ; 0x4000 * 0x400(KB unit size) = 16MB Flash_A0 size.
|
|
Data.Set A:&FLEXSPI_BASE+0x064 %LE %Long 0x00000000 ; 0x4000 * 0x400(KB unit size) = 16MB Flash_A1 size.
|
|
Data.Set A:&FLEXSPI_BASE+0x068 %LE %Long 0x00010000 ; 0x4000 * 0x400(KB unit size) = 16MB Flash_B0 size.
|
|
Data.Set A:&FLEXSPI_BASE+0x068 %LE %Long 0x00010000 ; 0x4000 * 0x400(KB unit size) = 16MB Flash_B1 size.
|
|
|
|
//timing
|
|
Data.Set A:&FLEXSPI_BASE+0x070 %LE %Long 0x00000063
|
|
Data.Set A:&FLEXSPI_BASE+0x074 %LE %Long 0x00000063
|
|
Data.Set A:&FLEXSPI_BASE+0x078 %LE %Long 0x00000063
|
|
Data.Set A:&FLEXSPI_BASE+0x07C %LE %Long 0x00000063
|
|
|
|
Data.Set A:&FLEXSPI_BASE+0x080 %LE %Long 0x00000900
|
|
Data.Set A:&FLEXSPI_BASE+0x084 %LE %Long 0x00000900
|
|
Data.Set A:&FLEXSPI_BASE+0x088 %LE %Long 0x00000900
|
|
Data.Set A:&FLEXSPI_BASE+0x08C %LE %Long 0x00000900
|
|
|
|
|
|
PER.Set.simple AZSD:0x40134010 %Long -1 ;interrupt enable
|
|
Data.Set A:&FLEXSPI_BASE+0x0B8 %LE %Long 0x0 ; water marker level 0 , reset assert 0x1
|
|
Data.Set A:&FLEXSPI_BASE+0x0BC %LE %Long (0x7<<2.) ; write tx fifo == 0x40 0x1C ; water marker level 0 , reset assert 0x1
|
|
|
|
Data.Set A:&FLEXSPI_BASE+0x0C0 %LE %Long 0x79
|
|
Data.Set A:&FLEXSPI_BASE+0x0C4 %LE %Long 0x0100
|
|
|
|
//LUT0 for read the spi memory data to the AHB
|
|
//FAST READ Quad I/O
|
|
; Data.Set A:&FLEXSPI_BASE+0x200 %LE %Long 0x0A1804EB
|
|
; Data.Set A:&FLEXSPI_BASE+0x204 %LE %Long 0x26043206
|
|
; Data.Set A:&FLEXSPI_BASE+0x208 %LE %Long 0x00
|
|
; Data.Set A:&FLEXSPI_BASE+0x20C %LE %Long 0x00
|
|
|
|
//Normal Read Mode
|
|
Data.Set A:&FLEXSPI_BASE+0x200 %LE %Long 0x08180403
|
|
Data.Set A:&FLEXSPI_BASE+0x204 %LE %Long 0x00002404
|
|
Data.Set A:&FLEXSPI_BASE+0x208 %LE %Long 0x00
|
|
Data.Set A:&FLEXSPI_BASE+0x20C %LE %Long 0x00
|
|
|
|
//Octal Read Mode
|
|
; Data.Set A:&FLEXSPI_BASE+0x200 %LE %Long 0x071307EC
|
|
; Data.Set A:&FLEXSPI_BASE+0x204 %LE %Long 0x0F140B20
|
|
; Data.Set A:&FLEXSPI_BASE+0x208 %LE %Long 0x00001F01
|
|
; Data.Set A:&FLEXSPI_BASE+0x20C %LE %Long 0x00
|
|
|
|
//Octal DDR Read Mode
|
|
; Data.Set ZSD:0x40134200 %LE %Long 0x871187EE
|
|
; Data.Set ZSD:0x40134204 %LE %Long 0xB3048B20
|
|
; Data.Set ZSD:0x40134208 %LE %Long 0x0000A704
|
|
; Data.Set ZSD:0x4013420C %LE %Long 0x00000000
|
|
|
|
//AHB update automatically even though the window size is < 1KB
|
|
Data.Set A:&FLEXSPI_BASE+0x00C %LE %Long Data.Long(A:&FLEXSPI_BASE+0x00C)&~0x20
|
|
|
|
RETURN
|
|
)
|
|
|
|
IOMUXconfig:
|
|
(
|
|
;for example, PIOnn_XX= 0x40004000+(nn*0x80+XX*4)
|
|
Data.Set ZSD:0x40004000+0x0AC %LE %Long 0x146 ; PIO1_11
|
|
Data.Set ZSD:0x40004000+0x0B0 %LE %Long 0x146 ; PIO1_12
|
|
Data.Set ZSD:0x40004000+0x0B4 %LE %Long 0x146 ; PIO1_13
|
|
Data.Set ZSD:0x40004000+0x0B8 %LE %Long 0x146 ; PIO1_14
|
|
Data.Set ZSD:0x40004000+0x0F4 %LE %Long 0x145 ; PIO1_29, clk
|
|
Data.Set ZSD:0x40004000+0x144 %LE %Long 0x146 ; PIO2_17
|
|
Data.Set ZSD:0x40004000+0x148 %LE %Long 0x146 ; PIO2_18
|
|
Data.Set ZSD:0x40004000+0x14C %LE %Long 0x146 ; PIO2_19
|
|
Data.Set ZSD:0x40004000+0x158 %LE %Long 0x146 ; PIO2_22
|
|
Data.Set ZSD:0x40004000+0x15C %LE %Long 0x146 ; PIO2_23
|
|
|
|
RETURN
|
|
)
|
|
|
|
|
|
IOMUXconfig_1:
|
|
(
|
|
;PIO1_20= 0+0x80+(20.x4)h
|
|
;1_18--1_29
|
|
Data.Set ZSD:0x400040C8 %LE %Long 0x141 ;PIO1_18
|
|
Data.Set ZSD:0x400040CC %LE %Long 0x141 ;PIO1_19
|
|
Data.Set ZSD:0x400040D0 %LE %Long 0x141 ;PIO1_20
|
|
Data.Set ZSD:0x400040D4 %LE %Long 0x141 ;PIO1_21
|
|
Data.Set ZSD:0x400040D8 %LE %Long 0x141 ;PIO1_22
|
|
Data.Set ZSD:0x400040DC %LE %Long 0x141 ;PIO1_23
|
|
Data.Set ZSD:0x400040E0 %LE %Long 0x141 ;PIO1_24
|
|
Data.Set ZSD:0x400040E4 %LE %Long 0x141 ;PIO1_25
|
|
Data.Set ZSD:0x400040E8 %LE %Long 0x141 ;PIO1_26
|
|
Data.Set ZSD:0x400040EC %LE %Long 0x141 ;PIO1_27
|
|
Data.Set ZSD:0x400040F0 %LE %Long 0x151 ;PIO1_28
|
|
Data.Set ZSD:0x400040F4 %LE %Long 0x131 ;PIO1_29
|
|
|
|
RETURN
|
|
)
|
|
|
|
|
|
READ_ID_TEST:
|
|
(
|
|
PRINT "READ_ID_TEST..."
|
|
|
|
Data.Set ASD:&FLEXSPI_BASE+0x80 %LE %Long 0x80000900 ;FLASHCR2
|
|
|
|
Data.Set ASD:&FLEXSPI_BASE+0x14 %LE %Long -1 ;INTR clear
|
|
|
|
Data.Set A:&FLEXSPI_BASE+0xB8 %Long 0x1 ;IPRXFCR
|
|
Data.Set A:&FLEXSPI_BASE+0xBC %Long 0x1 ;IPTXFCR
|
|
|
|
Data.Set A:&FLEXSPI_BASE+0x250 %LE %Long 0x2404049F ;readid with 4 bytes READ data
|
|
Data.Set A:&FLEXSPI_BASE+0x254 %LE %Long 0x0 ;
|
|
Data.Set A:&FLEXSPI_BASE+0x258 %LE %Long 0x0 ;
|
|
Data.Set A:&FLEXSPI_BASE+0x25c %LE %Long 0x0 ;
|
|
|
|
Data.Set A:&FLEXSPI_BASE+0x0A4 %LE %Long (5.<<16.)|0x4
|
|
|
|
Data.Set A:&FLEXSPI_BASE+0x0B0 %LE %Long 1 ;start
|
|
|
|
PRINT "1st 0x" Data.Long(A:&FLEXSPI_BASE+0x100)&0xFF " (Manufacturer)"
|
|
PRINT "2nd 0x" (Data.Long(A:&FLEXSPI_BASE+0x100)>>8.)&0xFF " (Device ID)"
|
|
PRINT "3rd 0x" (Data.Long(A:&FLEXSPI_BASE+0x100)>>16.)&0xFF
|
|
PRINT "4th 0x" Data.Long(A:&FLEXSPI_BASE+0x100)>>24.
|
|
|
|
RETURN
|
|
)
|
|
|
|
RESET_Memory:
|
|
(
|
|
PRINT "RESET Memory..."
|
|
|
|
Data.Set ASD:&FLEXSPI_BASE+0x80 %LE %Long 0x80000900 ;FLASHCR2
|
|
|
|
Data.Set ASD:&FLEXSPI_BASE+0x14 %LE %Long -1 ;INTR clear
|
|
|
|
Data.Set A:&FLEXSPI_BASE+0xB8 %Long 0x1 ;IPRXFCR
|
|
Data.Set A:&FLEXSPI_BASE+0xBC %Long 0x1 ;IPTXFCR
|
|
|
|
Data.Set A:&FLEXSPI_BASE+0x250 %LE %Long 0x00000466 ;readid with 4 bytes READ data
|
|
Data.Set A:&FLEXSPI_BASE+0x254 %LE %Long 0x0 ;
|
|
Data.Set A:&FLEXSPI_BASE+0x258 %LE %Long 0x0 ;
|
|
Data.Set A:&FLEXSPI_BASE+0x25c %LE %Long 0x0 ;
|
|
|
|
Data.Set A:&FLEXSPI_BASE+0x0A4 %LE %Long (5.<<16.)|0x4
|
|
|
|
Data.Set A:&FLEXSPI_BASE+0x0B0 %LE %Long 1 ;start
|
|
|
|
Data.Set A:&FLEXSPI_BASE+0x250 %LE %Long 0x00000499 ;readid with 4 bytes READ data
|
|
Data.Set A:&FLEXSPI_BASE+0x254 %LE %Long 0x0 ;
|
|
Data.Set A:&FLEXSPI_BASE+0x258 %LE %Long 0x0 ;
|
|
Data.Set A:&FLEXSPI_BASE+0x25c %LE %Long 0x0 ;
|
|
|
|
Data.Set A:&FLEXSPI_BASE+0x0A4 %LE %Long (5.<<16.)|0x4
|
|
|
|
Data.Set A:&FLEXSPI_BASE+0x0B0 %LE %Long 1 ;start
|
|
|
|
|
|
RETURN
|
|
)
|
|
|
|
|
|
READ_ID_TEST_OCTAL_DDR:
|
|
(
|
|
PRINT "READ_ID_TEST..."
|
|
|
|
Data.Set ASD:&FLEXSPI_BASE+0x80 %LE %Long 0x80000900 ;FLASHCR2
|
|
|
|
Data.Set ASD:&FLEXSPI_BASE+0x14 %LE %Long -1 ;INTR clear
|
|
|
|
Data.Set A:&FLEXSPI_BASE+0xB8 %Long 0x1 ;IPRXFCR
|
|
Data.Set A:&FLEXSPI_BASE+0xBC %Long 0x1 ;IPTXFCR
|
|
|
|
Data.Set A:&FLEXSPI_BASE+0x250 %LE %Long 0x8760879F ;readid with 4 bytes READ data
|
|
Data.Set A:&FLEXSPI_BASE+0x254 %LE %Long 0xB3048B20 ;
|
|
Data.Set A:&FLEXSPI_BASE+0x258 %LE %Long 0x0000A740 ;
|
|
Data.Set A:&FLEXSPI_BASE+0x25c %LE %Long 0x0 ;
|
|
|
|
Data.Set A:&FLEXSPI_BASE+0x0A0 %Long 0x00000000 ;IPCR0 , address register
|
|
|
|
Data.Set A:&FLEXSPI_BASE+0x0A4 %LE %Long (5.<<16.)|0x40
|
|
|
|
Data.Set A:&FLEXSPI_BASE+0x0B0 %LE %Long 1 ;start
|
|
|
|
PRINT "1st 0x" Data.Long(A:&FLEXSPI_BASE+0x100)&0xFF " (Manufacturer)"
|
|
PRINT "2nd 0x" (Data.Long(A:&FLEXSPI_BASE+0x100)>>8.)&0xFF " (Device ID)"
|
|
PRINT "3rd 0x" (Data.Long(A:&FLEXSPI_BASE+0x100)>>16.)&0xFF
|
|
PRINT "4th 0x" Data.Long(A:&FLEXSPI_BASE+0x100)>>24.
|
|
|
|
PRINT "5st 0x" Data.Long(A:&FLEXSPI_BASE+0x104)&0xFF " (Manufacturer)"
|
|
PRINT "6nd 0x" (Data.Long(A:&FLEXSPI_BASE+0x104)>>8.)&0xFF " (Device ID)"
|
|
PRINT "7rd 0x" (Data.Long(A:&FLEXSPI_BASE+0x104)>>16.)&0xFF
|
|
PRINT "8th 0x" Data.Long(A:&FLEXSPI_BASE+0x104)>>24.
|
|
|
|
RETURN
|
|
)
|
|
|
|
|
|
RESET_Memory_OCTAL_DDR:
|
|
(
|
|
PRINT "RESET Memory..."
|
|
|
|
Data.Set ASD:&FLEXSPI_BASE+0x80 %LE %Long 0x80000900 ;FLASHCR2
|
|
Data.Set ASD:&FLEXSPI_BASE+0x14 %LE %Long -1 ;INTR clear
|
|
Data.Set A:&FLEXSPI_BASE+0xB8 %Long 0x1 ;IPRXFCR
|
|
Data.Set A:&FLEXSPI_BASE+0xBC %Long 0x1 ;IPTXFCR
|
|
|
|
Data.Set A:&FLEXSPI_BASE+0x250 %LE %Long 0x87998766 ;readid with 4 bytes READ data
|
|
Data.Set A:&FLEXSPI_BASE+0x254 %LE %Long 0x0 ;
|
|
Data.Set A:&FLEXSPI_BASE+0x258 %LE %Long 0x0 ;
|
|
Data.Set A:&FLEXSPI_BASE+0x25c %LE %Long 0x0 ;
|
|
|
|
Data.Set A:&FLEXSPI_BASE+0x0A4 %LE %Long (5.<<16.)|0x4
|
|
Data.Set A:&FLEXSPI_BASE+0x0B0 %LE %Long 1 ;start
|
|
|
|
Data.Set ASD:&FLEXSPI_BASE+0x80 %LE %Long 0x80000900 ;FLASHCR2
|
|
Data.Set ASD:&FLEXSPI_BASE+0x14 %LE %Long -1 ;INTR clear
|
|
Data.Set A:&FLEXSPI_BASE+0xB8 %Long 0x1 ;IPRXFCR
|
|
Data.Set A:&FLEXSPI_BASE+0xBC %Long 0x1 ;IPTXFCR
|
|
|
|
Data.Set A:&FLEXSPI_BASE+0x250 %LE %Long 0x87668799 ;readid with 4 bytes READ data
|
|
Data.Set A:&FLEXSPI_BASE+0x254 %LE %Long 0x0 ;
|
|
Data.Set A:&FLEXSPI_BASE+0x258 %LE %Long 0x0 ;
|
|
Data.Set A:&FLEXSPI_BASE+0x25c %LE %Long 0x0 ;
|
|
|
|
Data.Set A:&FLEXSPI_BASE+0x0A4 %LE %Long (5.<<16.)|0x4
|
|
Data.Set A:&FLEXSPI_BASE+0x0B0 %LE %Long 1 ;start
|
|
|
|
RETURN
|
|
)
|
|
|