mirror of
https://github.com/RT-Thread/rt-thread.git
synced 2025-02-19 07:32:02 +08:00
[nrfx] add the qspi_flash of nordic pdk
This commit is contained in:
parent
084996ddb5
commit
979cec4af6
@ -14,6 +14,9 @@ if GetDepend(['BSP_USING_UART']):
|
|||||||
if GetDepend(['BSP_USING_ON_CHIP_FLASH']):
|
if GetDepend(['BSP_USING_ON_CHIP_FLASH']):
|
||||||
src += ['drv_flash.c']
|
src += ['drv_flash.c']
|
||||||
|
|
||||||
|
if GetDepend(['BSP_USING_QSPI_FLASH']):
|
||||||
|
src += ['drv_qspi_flash.c']
|
||||||
|
|
||||||
path = [cwd]
|
path = [cwd]
|
||||||
|
|
||||||
group = DefineGroup('Drivers', src, depend = [''], CPPPATH = path)
|
group = DefineGroup('Drivers', src, depend = [''], CPPPATH = path)
|
||||||
|
@ -13,8 +13,6 @@
|
|||||||
#include "nrfx_nvmc.h"
|
#include "nrfx_nvmc.h"
|
||||||
|
|
||||||
#ifdef BSP_USING_ON_CHIP_FLASH
|
#ifdef BSP_USING_ON_CHIP_FLASH
|
||||||
//#include "drv_config.h"
|
|
||||||
#include "drv_flash.h"
|
|
||||||
|
|
||||||
#if defined(PKG_USING_FAL)
|
#if defined(PKG_USING_FAL)
|
||||||
#include "fal.h"
|
#include "fal.h"
|
||||||
@ -163,8 +161,6 @@ static int fal_flash_read(long offset, rt_uint8_t *buf, size_t size);
|
|||||||
static int fal_flash_write(long offset, const rt_uint8_t *buf, size_t size);
|
static int fal_flash_write(long offset, const rt_uint8_t *buf, size_t size);
|
||||||
static int fal_flash_erase(long offset, size_t size);
|
static int fal_flash_erase(long offset, size_t size);
|
||||||
|
|
||||||
const struct fal_flash_dev mcu_onchip_flash = {"mcu_onchip", MCU_FLASH_START_ADDRESS, MCU_FLASH_SIZE, MCU_FLASH_PAGE_SIZE, {NULL, fal_flash_read, fal_flash_write, fal_flash_erase} };
|
|
||||||
|
|
||||||
static int fal_flash_read(long offset, rt_uint8_t *buf, size_t size)
|
static int fal_flash_read(long offset, rt_uint8_t *buf, size_t size)
|
||||||
{
|
{
|
||||||
return mcu_flash_read(mcu_onchip_flash.addr + offset, buf, size);
|
return mcu_flash_read(mcu_onchip_flash.addr + offset, buf, size);
|
||||||
@ -179,6 +175,14 @@ static int fal_flash_erase(long offset, size_t size)
|
|||||||
{
|
{
|
||||||
return mcu_flash_erase(mcu_onchip_flash.addr + offset, size);
|
return mcu_flash_erase(mcu_onchip_flash.addr + offset, size);
|
||||||
}
|
}
|
||||||
|
const struct fal_flash_dev mcu_onchip_flash =
|
||||||
|
{
|
||||||
|
.name = ON_CHIP_FLASH_DEV_NAME,
|
||||||
|
.addr = MCU_FLASH_START_ADDRESS,
|
||||||
|
.len = MCU_FLASH_SIZE,
|
||||||
|
.blk_size = MCU_FLASH_PAGE_SIZE,
|
||||||
|
.ops = {NULL, fal_flash_read, fal_flash_write, fal_flash_erase},
|
||||||
|
.write_gran = 8
|
||||||
|
};
|
||||||
#endif
|
#endif
|
||||||
#endif /* BSP_USING_ON_CHIP_FLASH */
|
#endif /* BSP_USING_ON_CHIP_FLASH */
|
||||||
|
@ -1,29 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2006-2018, RT-Thread Development Team
|
|
||||||
*
|
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
|
||||||
*
|
|
||||||
* Change Logs:
|
|
||||||
* Date Author Notes
|
|
||||||
* 2020-04-29 supperthomas first version
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef __DRV_FLASH_H__
|
|
||||||
#define __DRV_FLASH_H__
|
|
||||||
|
|
||||||
#include <rtdevice.h>
|
|
||||||
#include <rthw.h>
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
int nrfx_flash_read(rt_uint32_t addr, rt_uint8_t *buf, size_t size);
|
|
||||||
int nrfx_flash_write(rt_uint32_t addr, const rt_uint8_t *buf, size_t size);
|
|
||||||
int nrfx_flash_erase(rt_uint32_t addr, size_t size);
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif /* __DRV_FLASH_H__ */
|
|
153
bsp/nrf5x/libraries/drivers/drv_qspi_flash.c
Normal file
153
bsp/nrf5x/libraries/drivers/drv_qspi_flash.c
Normal file
@ -0,0 +1,153 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2006-2020, RT-Thread Development Team
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*
|
||||||
|
* Change Logs:
|
||||||
|
* Date Author Notes
|
||||||
|
* 2020-04-29 supperthomas first version
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
#include <stdint.h>
|
||||||
|
#include "board.h"
|
||||||
|
#include "nrfx_qspi.h"
|
||||||
|
#if defined(PKG_USING_FAL)
|
||||||
|
#include <fal.h>
|
||||||
|
|
||||||
|
//log
|
||||||
|
#include <rtdbg.h>
|
||||||
|
#define LOG_TAG "drv.qspiflash"
|
||||||
|
|
||||||
|
#define WAIT_FOR_PERIPH() do { \
|
||||||
|
while (!m_finished) {} \
|
||||||
|
m_finished = false; \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
static volatile bool m_finished = false;
|
||||||
|
static void qspi_handler(nrfx_qspi_evt_t event, void *p_context)
|
||||||
|
{
|
||||||
|
m_finished = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void configure_memory()
|
||||||
|
{
|
||||||
|
#define QSPI_STD_CMD_WRSR 0x01
|
||||||
|
#define QSPI_STD_CMD_RSTEN 0x66
|
||||||
|
#define QSPI_STD_CMD_RST 0x99
|
||||||
|
|
||||||
|
uint8_t temporary = 0x40;
|
||||||
|
uint32_t err_code;
|
||||||
|
nrf_qspi_cinstr_conf_t cinstr_cfg =
|
||||||
|
{
|
||||||
|
.opcode = QSPI_STD_CMD_RSTEN,
|
||||||
|
.length = NRF_QSPI_CINSTR_LEN_1B,
|
||||||
|
.io2_level = true,
|
||||||
|
.io3_level = true,
|
||||||
|
.wipwait = true,
|
||||||
|
.wren = true
|
||||||
|
};
|
||||||
|
|
||||||
|
// Send reset enable
|
||||||
|
err_code = nrfx_qspi_cinstr_xfer(&cinstr_cfg, NULL, NULL);
|
||||||
|
if (NRFX_SUCCESS != err_code)
|
||||||
|
{
|
||||||
|
LOG_E("\r\n ERROR: QSPI_STD_CMD_RSTEN:0x%x\n", err_code);
|
||||||
|
return ;
|
||||||
|
}
|
||||||
|
// Send reset command
|
||||||
|
cinstr_cfg.opcode = QSPI_STD_CMD_RST;
|
||||||
|
err_code = nrfx_qspi_cinstr_xfer(&cinstr_cfg, NULL, NULL);
|
||||||
|
if (NRFX_SUCCESS != err_code)
|
||||||
|
{
|
||||||
|
LOG_E("\r\n ERROR: QSPI_STD_CMD_RST:0x%x\n", err_code);
|
||||||
|
return ;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Switch to qspi mode
|
||||||
|
cinstr_cfg.opcode = QSPI_STD_CMD_WRSR;
|
||||||
|
cinstr_cfg.length = NRF_QSPI_CINSTR_LEN_2B;
|
||||||
|
err_code = nrfx_qspi_cinstr_xfer(&cinstr_cfg, &temporary, NULL);
|
||||||
|
if (NRFX_SUCCESS != err_code)
|
||||||
|
{
|
||||||
|
LOG_E("\r\n ERROR: QSPI_STD_CMD_WRSR:0x%x\n", err_code);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
static int init(void)
|
||||||
|
{
|
||||||
|
uint32_t err_code;
|
||||||
|
nrfx_qspi_config_t config = NRFX_QSPI_DEFAULT_CONFIG(BSP_QSPI_SCK_PIN, BSP_QSPI_CSN_PIN,
|
||||||
|
BSP_QSPI_IO0_PIN, BSP_QSPI_IO1_PIN, BSP_QSPI_IO2_PIN, BSP_QSPI_IO3_PIN);
|
||||||
|
|
||||||
|
err_code = nrfx_qspi_init(&config, qspi_handler, NULL);
|
||||||
|
if (NRFX_SUCCESS != err_code)
|
||||||
|
{
|
||||||
|
LOG_E("\r\n ERROR: QSPI_init:0x%x\n", err_code);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
configure_memory();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int read(long offset, uint8_t *buf, size_t size)
|
||||||
|
{
|
||||||
|
uint32_t err_code;
|
||||||
|
m_finished = false;
|
||||||
|
err_code = nrfx_qspi_read(buf, size, offset);
|
||||||
|
WAIT_FOR_PERIPH();
|
||||||
|
if (NRFX_SUCCESS == err_code)
|
||||||
|
{
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LOG_E("\r\n ERROR: read:0x%x\n", err_code);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int write(long offset, const uint8_t *buf, size_t size)
|
||||||
|
{
|
||||||
|
uint32_t err_code;
|
||||||
|
m_finished = false;
|
||||||
|
err_code = nrfx_qspi_write(buf, size, offset);
|
||||||
|
WAIT_FOR_PERIPH();
|
||||||
|
if (NRFX_SUCCESS == err_code)
|
||||||
|
{
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LOG_E("\r\n ERROR: write:0x%x\n", err_code);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int erase(long offset, size_t size)
|
||||||
|
{
|
||||||
|
uint32_t err_code;
|
||||||
|
m_finished = false;
|
||||||
|
err_code = nrfx_qspi_erase(NRF_QSPI_ERASE_LEN_64KB, offset);
|
||||||
|
WAIT_FOR_PERIPH();
|
||||||
|
if (NRFX_SUCCESS == err_code)
|
||||||
|
{
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LOG_E("\r\n ERROR: erase:0x%x\n", err_code);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct fal_flash_dev nor_flash0 =
|
||||||
|
{
|
||||||
|
.name = NOR_FLASH_DEV_NAME,
|
||||||
|
.addr = 0,
|
||||||
|
.len = QSPI_FLASH_SIZE_KB * 1024,
|
||||||
|
.blk_size = 4096,
|
||||||
|
.ops = {init, read, write, erase},
|
||||||
|
.write_gran = 1
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
@ -13,6 +13,41 @@ menu "Onboard Peripheral Drivers"
|
|||||||
select BSP_USING_UART
|
select BSP_USING_UART
|
||||||
select BSP_USING_UART0
|
select BSP_USING_UART0
|
||||||
default y
|
default y
|
||||||
|
|
||||||
|
menuconfig BSP_USING_QSPI_FLASH
|
||||||
|
select PKG_USING_FAL
|
||||||
|
bool "Enable QSPI FLASH(MX25R64 8MB)"
|
||||||
|
default n
|
||||||
|
|
||||||
|
if BSP_USING_QSPI_FLASH
|
||||||
|
config BSP_QSPI_SCK_PIN
|
||||||
|
int "QSPI SCK pin number"
|
||||||
|
range 0 31
|
||||||
|
default 19
|
||||||
|
config BSP_QSPI_CSN_PIN
|
||||||
|
int "QSPI CSN pin number"
|
||||||
|
range 0 31
|
||||||
|
default 17
|
||||||
|
config BSP_QSPI_IO0_PIN
|
||||||
|
int "QSPI IO0 pin number"
|
||||||
|
range 0 31
|
||||||
|
default 20
|
||||||
|
config BSP_QSPI_IO1_PIN
|
||||||
|
int "QSPI IO1 pin number"
|
||||||
|
range 0 31
|
||||||
|
default 21
|
||||||
|
config BSP_QSPI_IO2_PIN
|
||||||
|
int "QSPI IO2 pin number"
|
||||||
|
range 0 31
|
||||||
|
default 22
|
||||||
|
config BSP_QSPI_IO3_PIN
|
||||||
|
int "QSPI IO3 pin number"
|
||||||
|
range 0 31
|
||||||
|
default 23
|
||||||
|
config QSPI_FLASH_SIZE_KB
|
||||||
|
int "QSPI FLASH SIZE, DEFAULT size 8192 KB"
|
||||||
|
default 8192
|
||||||
|
endif
|
||||||
endmenu
|
endmenu
|
||||||
|
|
||||||
menu "On-chip Peripheral Drivers"
|
menu "On-chip Peripheral Drivers"
|
||||||
@ -44,29 +79,37 @@ menu "On-chip Peripheral Drivers"
|
|||||||
bool "Enable UART1"
|
bool "Enable UART1"
|
||||||
default n
|
default n
|
||||||
endif
|
endif
|
||||||
menu "On-chip flash config"
|
|
||||||
config MCU_FLASH_START_ADDRESS
|
config BSP_USING_ON_CHIP_FLASH
|
||||||
hex "MCU FLASH START ADDRESS"
|
select PKG_USING_FAL
|
||||||
default 0x00000000
|
bool "Enable on-chip FLASH"
|
||||||
|
default n
|
||||||
config MCU_FLASH_SIZE_KB
|
|
||||||
int "MCU FLASH SIZE, MAX size 1024 KB"
|
menu "On-chip flash config"
|
||||||
range 1 1024
|
|
||||||
default 1024
|
|
||||||
|
config MCU_FLASH_START_ADDRESS
|
||||||
config MCU_SRAM_START_ADDRESS
|
hex "MCU FLASH START ADDRESS"
|
||||||
hex "MCU RAM START ADDRESS"
|
default 0x00000000
|
||||||
default 0x20000000
|
|
||||||
|
config MCU_FLASH_SIZE_KB
|
||||||
config MCU_SRAM_SIZE_KB
|
int "MCU FLASH SIZE, MAX size 1024 KB"
|
||||||
int "MCU RAM SIZE, MAX size 256 KB"
|
range 1 1024
|
||||||
range 1 256
|
default 1024
|
||||||
default 256
|
|
||||||
|
config MCU_SRAM_START_ADDRESS
|
||||||
config MCU_FLASH_PAGE_SIZE
|
hex "MCU RAM START ADDRESS"
|
||||||
hex "MCU FLASH PAGE SIZE, please not change,nrfx default is 0x1000"
|
default 0x20000000
|
||||||
range 0x1000 0x1000
|
|
||||||
default 0x1000
|
config MCU_SRAM_SIZE_KB
|
||||||
|
int "MCU RAM SIZE, MAX size 256 KB"
|
||||||
|
range 1 256
|
||||||
|
default 256
|
||||||
|
|
||||||
|
config MCU_FLASH_PAGE_SIZE
|
||||||
|
hex "MCU FLASH PAGE SIZE, please not change,nrfx default is 0x1000"
|
||||||
|
range 0x1000 0x1000
|
||||||
|
default 0x1000
|
||||||
endmenu
|
endmenu
|
||||||
endmenu
|
endmenu
|
||||||
|
|
||||||
|
82
bsp/nrf5x/nrf52840/board/fal_cfg.h
Normal file
82
bsp/nrf5x/nrf52840/board/fal_cfg.h
Normal file
@ -0,0 +1,82 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2006-2020, RT-Thread Development Team
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*
|
||||||
|
* Change Logs:
|
||||||
|
* Date Author Notes
|
||||||
|
* 2020-05-05 supperthomas this is sample you can change by yourself
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _FAL_CFG_H_
|
||||||
|
#define _FAL_CFG_H_
|
||||||
|
|
||||||
|
#include <rtconfig.h>
|
||||||
|
#include <board.h>
|
||||||
|
|
||||||
|
#if (defined(BSP_USING_QSPI_FLASH)&&defined(BSP_USING_ON_CHIP_FLASH))
|
||||||
|
|
||||||
|
#define ON_CHIP_FLASH_DEV_NAME "mcu_onchip"
|
||||||
|
#define NOR_FLASH_DEV_NAME "norflash0"
|
||||||
|
|
||||||
|
extern const struct fal_flash_dev mcu_onchip_flash;
|
||||||
|
extern struct fal_flash_dev nor_flash0;
|
||||||
|
|
||||||
|
/* flash device table */
|
||||||
|
#define FAL_FLASH_DEV_TABLE \
|
||||||
|
{ \
|
||||||
|
&mcu_onchip_flash, \
|
||||||
|
&nor_flash0, \
|
||||||
|
}
|
||||||
|
/* ====================== Partition Configuration ========================== */
|
||||||
|
#ifdef FAL_PART_HAS_TABLE_CFG
|
||||||
|
/* partition table */
|
||||||
|
#define FAL_PART_TABLE \
|
||||||
|
{ \
|
||||||
|
{FAL_PART_MAGIC_WORD, "bl", ON_CHIP_FLASH_DEV_NAME, 0, 64*1024, 0}, \
|
||||||
|
{FAL_PART_MAGIC_WORD, "app_flash", ON_CHIP_FLASH_DEV_NAME, 64*1024, 960*1024, 0}, \
|
||||||
|
{FAL_PART_MAGIC_WORD, "nor_flash_part_0", NOR_FLASH_DEV_NAME, 0, 1024*1024, 0}, \
|
||||||
|
{FAL_PART_MAGIC_WORD, "nor_flash_part_1", NOR_FLASH_DEV_NAME, 1024*1024, 7*1024*1024, 0}, \
|
||||||
|
}
|
||||||
|
#endif /* FAL_PART_HAS_TABLE_CFG */
|
||||||
|
|
||||||
|
#elif defined(BSP_USING_QSPI_FLASH)
|
||||||
|
|
||||||
|
#define NOR_FLASH_DEV_NAME "norflash0"
|
||||||
|
extern struct fal_flash_dev nor_flash0;
|
||||||
|
|
||||||
|
/* flash device table */
|
||||||
|
#define FAL_FLASH_DEV_TABLE \
|
||||||
|
{ \
|
||||||
|
&nor_flash0, \
|
||||||
|
}
|
||||||
|
/* ====================== Partition Configuration ========================== */
|
||||||
|
#ifdef FAL_PART_HAS_TABLE_CFG
|
||||||
|
/* partition table */
|
||||||
|
#define FAL_PART_TABLE \
|
||||||
|
{ \
|
||||||
|
{FAL_PART_MAGIC_WORD, "nor_flash_part_0", NOR_FLASH_DEV_NAME, 0, 1024*1024, 0}, \
|
||||||
|
{FAL_PART_MAGIC_WORD, "nor_flash_part_1", NOR_FLASH_DEV_NAME, 1024*1024, 7*1024*1024, 0}, \
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#elif defined(BSP_USING_ON_CHIP_FLASH)
|
||||||
|
extern const struct fal_flash_dev mcu_onchip_flash;
|
||||||
|
#define ON_CHIP_FLASH_DEV_NAME "mcu_onchip"
|
||||||
|
/* flash device table */
|
||||||
|
#define FAL_FLASH_DEV_TABLE \
|
||||||
|
{ \
|
||||||
|
&mcu_onchip_flash, \
|
||||||
|
}
|
||||||
|
/* ====================== Partition Configuration ========================== */
|
||||||
|
#ifdef FAL_PART_HAS_TABLE_CFG
|
||||||
|
/* partition table */
|
||||||
|
#define FAL_PART_TABLE \
|
||||||
|
{ \
|
||||||
|
{FAL_PART_MAGIC_WORD, "bl", ON_CHIP_FLASH_DEV_NAME, 0, 64*1024, 0}, \
|
||||||
|
{FAL_PART_MAGIC_WORD, "app_flash", ON_CHIP_FLASH_DEV_NAME, 64*1024, 960*1024, 0}, \
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* _FAL_CFG_H_ */
|
@ -2902,7 +2902,7 @@
|
|||||||
// <e> NRFX_QSPI_ENABLED - nrfx_qspi - QSPI peripheral driver
|
// <e> NRFX_QSPI_ENABLED - nrfx_qspi - QSPI peripheral driver
|
||||||
//==========================================================
|
//==========================================================
|
||||||
#ifndef NRFX_QSPI_ENABLED
|
#ifndef NRFX_QSPI_ENABLED
|
||||||
#define NRFX_QSPI_ENABLED 0
|
#define NRFX_QSPI_ENABLED 1
|
||||||
#endif
|
#endif
|
||||||
// <o> NRFX_QSPI_CONFIG_SCK_DELAY - tSHSL, tWHSL and tSHWL in number of 16 MHz periods (62.5 ns). <0-255>
|
// <o> NRFX_QSPI_CONFIG_SCK_DELAY - tSHSL, tWHSL and tSHWL in number of 16 MHz periods (62.5 ns). <0-255>
|
||||||
|
|
||||||
@ -3010,7 +3010,7 @@
|
|||||||
#define NRFX_QSPI_PIN_IO3 NRF_QSPI_PIN_NOT_CONNECTED
|
#define NRFX_QSPI_PIN_IO3 NRF_QSPI_PIN_NOT_CONNECTED
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// <o> NRFX_QSPI_CONFIG_IRQ_PRIORITY - Interrupt priority
|
// <o> NRFX_QSPI_DEFAULT_CONFIG_IRQ_PRIORITY - Interrupt priority
|
||||||
|
|
||||||
// <0=> 0 (highest)
|
// <0=> 0 (highest)
|
||||||
// <1=> 1
|
// <1=> 1
|
||||||
@ -3021,8 +3021,8 @@
|
|||||||
// <6=> 6
|
// <6=> 6
|
||||||
// <7=> 7
|
// <7=> 7
|
||||||
|
|
||||||
#ifndef NRFX_QSPI_CONFIG_IRQ_PRIORITY
|
#ifndef NRFX_QSPI_DEFAULT_CONFIG_IRQ_PRIORITY
|
||||||
#define NRFX_QSPI_CONFIG_IRQ_PRIORITY 6
|
#define NRFX_QSPI_DEFAULT_CONFIG_IRQ_PRIORITY 6
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// </e>
|
// </e>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user