ESP-12F WIFI模块开发(NonOS, RTOS, NodeMCU固件编译)(原创)



  • 2020-08 新增RTOS固件编译和NodeMCU固件编译内容



一、概述

ESP8266/ESP8285 系列模组是深圳市安信可科技有限公司开发的一系列基于乐鑫ESP8266EX/ESP8285的低功耗UART-WiFi芯片模组,可以方便地进行二次开发,接入云端服务,实现手机3/4G全球随时随地的控制,加速产品原型设计。

模块核心处理器 ESP8266/ESP8285 在较小尺寸封装中集成了业界领先的 Tensilica L106 超低功耗 32 位微型 MCU,带有 16 位精简模式,主频支持 80 MHz 和 160 MHz,支持 RTOS,集成 Wi-Fi MAC/ BB/RF/PA/LNA,板载天线。支持标准的 IEEE802.11 b/g/n 协议,完整的 TCP/IP 协议栈。用户可以使用该模块为现有的设备添加联网功能,也可以构建独立的网络控制器。

ESP8266/ESP8285 是高性能无线 SoC,以最低成本提供最大实用性,为 Wi-Fi 功能嵌入其他系统提供无限可能。


特点

  • 802.11 b/g/n
  • 内置Tensilica L106 超低功耗 32 位微型 MCU,主频支持 80 MHz 和160 MHz,支持 RTOS
  • 内置10 bit高精度ADC
  • 内置TCP/IP协议栈
  • 内置TR 开关、balun、LNA、功率放大器和匹配网络
  • 内置PLL、稳压器和电源管理组件,802.11b 模式下+18 dBm的输出功率
  • A-MPDU 、 A-MSDU 的聚合和 0.4 s的保护间隔
  • Wi-Fi @ 2.4 GHz,支持 WPA/WPA2 安全模式
  • 支持AT本地升级及云端OTA升级
  • 支持 STA/AP/STA+AP 工作模式
  • 支持 Smart Config 功能(包括 Android 和 iOS 设备)
  • HSPI 、UART、I2C、I2S、IR Remote Control、PWM、GPIO
  • 深度睡眠保持电流为 20 uA,关断电流小于 5 uA
  • 2 ms 之内唤醒、连接并传递数据包
  • 待机状态消耗功率小于1.0 mW (DTIM3)
  • 工作温度范围:详情请见具体型号规格书



二、安信可在售选型表

型号 ESP-01E ESP-01S ESP-01M ESP-07S ESP-12L ESP-12F ESP-12
封装 DIP-18 DIP-8 DIP-18 SMD-16 SMD-16 SMD-22 SMD-16
尺寸(mm) 18x17x2.8 24.7x14.4x11.0 18x18x2.8 17.0x16.0x3.0 24.0x16.0x3.0 24.0x16.0x3.0 24.0x16.0x3.0
板层 4 2 4 4 2 4 4
Flash 8Mbit/16Mbit 8Mbit 8Mbit/16Mbit 32Mbit 32Mbit 32Mbit 32Mbit
已认证 FCC、CE - FCC、CE、SRRC、REACH、RoHS FCC、CE、REACH、RoHS、SRRC SRRC、FCC、CE、RoHS FCC、CE、IC、SRRC、KCC、NCC、TELEC、ANATEL、REACH、RoHS FCC、SRRC、CE、RoHS
天线 IPEX天线 PCB天线 PCB天线 IPEX天线 PCB天线 PCB天线 PCB天线
指示灯 - GPIO2 - - GPIO2 GPIO2 GPIO2
可用IO 11 2 11 9 9 9 9

全系列模组购买请戳:安信可官方淘宝店

更多选型资料请查看 旧选型表 或咨询我们 sales@aithinker.com



启动信息解释

​ 在 ESP8266 启动时, ROM CODE 会读取 GPIO 状态和 rst cause 状态, 进而决定 ESP8266 工作模式。通过了解和掌握 rst causeboot mode, 有助于定位某些系统问题。

  • ROM CODE 波特率为 74880



ESP8266 启动时 rst cause 值的含义

ESP8266 启动时会有如下打印:

ets Jan 8 2013, cause:2, boot mode:(3,7)

其中 rst cause 说明如下:

枚举定义 意义
0 NO_MEAN 无意义
1 VBAT_REST 上电复位(电源重启)
2 EXT_SYS_RESET 外部复位 (deep-sleep 醒来)
3 SW_RESET 软件复位
4 WDT_RESET 硬件看门狗复位
5 DEEPSLEEP_TIMER_RESET -
6 DEEPSLEEP_POWER_ON_RESET -

Notes:

  • 软件 WDT 重启或者软件复位都会维持上次重启状态。比如第一次是电源重启, rst cause 为 1, 软件复位后 rst cause 仍然为 1 。



ESP8266 上电 boot mode 值得含义

ESP8266上电时会判断 boot strapping 管脚的状态, 并决定 boot mode

例如上电打印:

ets Jan 8 2013, cause:2, boot mode:(3,7)

其中 boot mode 说明如下:

  • 第一个值 代表当前 boot 模式
  • 第二个值 代表 SDIO/UART 判断

boot modestrapping 管脚的 3 位值 [GPIO15, GPIO0, GPIO2] 共同决定。如下表所示:

boot mode Strapping 管脚的 3 位值
[GPIO15, GPIO0, GPIO2]
SDIO/UART 判断 意义
0 [0, 0, 0] - remap boot
1 [0, 0, 1] - UART boot
2 [0, 1, 0] - jump boot
3 [0, 1, 1] - fast flash boot
4 [1, 0, 0] 2 SDIO lowspeed V1 UART boot
5 [1, 0, 1] 2 SDIO lowspeed v2 uart boot
6 [1, 1, 0] 2 SDIO highspeed v1 uart boot
7 [1, 1, 1] 2 SDIO highspeed v2 uart boot
4 - 7 [1,0,0], [1,0,1], [1,1,0], [1,1,1] 非 2 SDIO boot
  • boot mode 4~7 为 SDIO 的不同的协议标准, 包括低速 (lowspeed) 和高速 (highspeed), 版本号(V1, V2)等, 但并非所有 MCU 都会同时支持这些标准。

参考文档



启动模式设置

模式 CH_PD (EN) RST GPIO15 GPIO0 GPIO2 TXD0
下载模式
运行模式
测试模式 - - -

注意: 如果要进入下载模式,参考下面的接线图,在该接线的基础上将 GPIO0 接地即可。参考官方烧录章节,进行烧录。



电路连接图

下图参考官方文档:ESP8266系列入门教程。图中电阻均为10K。

注:

  • RST引脚可不用上拉,内部已经上拉处理。

  • TXD在上电期间应避免被外部下拉到低电平,否则模块不能启动。



固件烧录

**注意:**这里只介绍 ESP-12F 产品的固件烧录,是32Mbit的Flash。

**注意:**这里只介绍 ESP-12F 产品的固件烧录,是32Mbit的Flash。

其他产品请自行参考其资料做相应修改。



获取官方固件

其中

  • 乐鑫官网提供的固件:NonOS V1.7.0 - V1.7.4 版本都是按照16Mbit硬件配置编译的,烧录到ESP-12F需要按16Mbit模式的配置来下载。

    • V1.6.2固件可用于32Mbit的 ESP-12F 上。
  • 安信可固件:博安通 AT 固件 是基于NonOS V1.7.0的AT固件,内含8Mbit和32Mbit两个版本,

    • 其烧录程序设置:
    • SPI Speed:40MHz,
    • SPI mode: DOUT,
    • Flash Size:32Mbit-C1



固件文件说明

不支持云端升级 (NoBoot 模式)

文件名 32Mbit 地址分配 说明
eagle.flash.bin 0x00000 主程序,由代码编译生成
eagle.irom0text.bin 0x10000 主程序,由代码编译生成
blank.bin 0x3FB000 用于清空 RF_CAL参数区,由乐鑫在SDK中提供
esp_init_data_default_v08.bin 0x3FC000 配置文件,由乐鑫在SDK中提供
blank.bin 0x3FE000 用于清空 系统参数区,由乐鑫在SDK中提供

**注:**eagle.irom0text.bin的上限值参考《ESP8266_SDK入门指南 esp8266-sdk_getting_started_guide_cn.pdf》文档的 4.1节 进行修改,其他闪存容量参考 4.1节 进行设置。

支持云端升级 (Boot 模式)

文件名 32Mbit 地址分配
(1024+1024)
说明
boot.bin (boot_v1.x.bin) 0x00000 由乐鑫在SDK中提供,建议使用最新版本
user1.bin (user1.4096.new.6.bin) 0x01000 主程序,由代码编译生成
user2.bin (user2.4096.new.6.bin) 0x101000 主程序,由代码编译生成
blank.bin 0x3FB000 用于清空 RF_CAL参数区,由乐鑫在SDK中提供
esp_init_data_default_v08.bin 0x3FC000 配置文件,由乐鑫在SDK中提供
blank.bin 0x3FE000 用于清空 系统参数区,由乐鑫在SDK中提供

**注:**地址分配 参考《ESP8266_SDK入门指南 esp8266-sdk_getting_started_guide_cn.pdf》文档的 4.2节 进行修改,其他闪存容量参考 4.2节 进行设置。

**说明:**乐鑫官方提供的V1.7.x固件,user1.bin 是 user1.2048.new.5.bin 这是按照16Mbit的配置编译的。

**注意:**支持云端升级的 FOTA固件,在 flash 布局会分为两个区,一个用来执行程序,另一个用来保存要升级的固件。当程序运行在 user1 时开始升级,程序会下载到 user2 区域,下载完毕后,下次启动运行 user2 的程序,依次替换,实现云端升级。

  • User1.Bin 文件和 User2bin 文件在烧录时 只烧录其中一个即可。
  • Boot.bin 文件建议使用最新版本。



固件Flash布局图

分区说明:

  • Boot信息: 位于FOTA固件的分区1,存放Boot文件, 即FOTA升级相关信息。

  • 系统程序: 用于存放运行系统必要的固件。

  • 用户数据: 当有多余的Flash空间用于用户数据区时,空闲区域均可用于存放用户数据。用户可在其中任意空闲位置设置用户参数区,建议⾄至少为用户参数区预留12KB空间。

  • RF_CAL参数:用于系统自动保存校准后的 RF 参数。

  • 默认RF参数:将 esp_int_data_default.bin 下载至该区,用于保存默认的参数信息。

  • 系统参数:用于保存系统参数信息。

  • User.bin 其中user1.bin和user2.bin是同一个应用程序,选择不同的编译步骤分别生成的两个固件,存放在 SPI Flash 不同位置,启动时先运行 Boot,Boot 读取系统参数区中的标志位,判断运行行 user1.bin 还是user2.bin,然后到 SPI Flash 的对应位置读取运行。

注意:

  • Flash 中每扇区为 4KB。
  • ESP8266目前 系统程序区 最大支持 1024KB。



烧写固件程序

将ESP-12F模块的GPIO0引脚连接到GND,上电,模块进入下载模式。

串口提示信息如下:

ets Jan  8 2013,rst cause:2, boot mode:(1,7)



32Mflash烧写配置表(FOTA固件):

Bin文件 烧录地址 说明
boot.bin 0x00000 引导程序
user1.4096.new.6.bin 0x01000 用户程序
blank.bin 0x3FB000 初始化 RF_CAL 参数区
esp_init_data_default_v08.bin 0x3FC000 初始化其他射频参数区,至少烧录一次
当 RF_CAL 参数区初始化烧录时,本区域也会烧录
blank.bin 0x3FE000 初始化系统参数区

注:

  • 一般烧录,请使用工具 ESP Flash Download Tool

  • 建议按照烧录地址从低到高,按顺序排列烧录。

  • 支持FOTA的固件无需下载user2.bin,用户可以从云端服务器升级固件。

  • 详细的FOTA功能说明,请参考文档《ESP8266 云端升级指南》。

打开烧录软件,设置好选项,点击START开始烧录程序,如下图:(user1.bin是我自己编译的v1.7.4)

**再次说明:**乐鑫官方提供的V1.7.x固件,user1.bin 是 user1.2048.new.5.bin,其中5表示 5 = 2048KB(1024KB+1024KB) (见固件编译-make参数说明),这是按照16Mbit的配置编译的,所以烧录时要选择16Mbit-C1模式才能成功。

  • 要使用NonOS V1.7.0版本,可下载安信可提供的出厂固件:博安通 AT 固件

  • 使用V1.7.4版本固件,需要自己编译,编译固件方法见下文。



上电启动

烧录完成后,将GPIO0引脚悬空或上拉到VCC,上电启动模块,串口信息如下:

ets Jan  8 2013,rst cause:2, boot mode:(3,7)

load 0x40100000, len 2592, room 16 
tail 0
chksum 0xf3
load 0x3ffe8000, len 764, room 8 
tail 4
chksum 0x92
load 0x3ffe82fc, len 676, room 4 
tail 0
chksum 0x22
csum 0x22

2nd boot version : 1.7(5d6f877)
SPI Speed : 40MHz
SPI Mode : QIO
SPI Flash Size & Map: 32Mbit(1024KB+1024KB)

...

SDK ver: 3.0.5-dev(52383f9) compiled @ Jul  8 2020 16:00:05
phy ver: 1156_0, pp ver: 10.2

表示烧录成功。



官方固件合并配置图

  • 官方flash模式使用的DOUT模式。

  • 为什么要合并?

    使用软件上的 CombineBin 按键可以将文件打包合并成一个完整的固件。

    • ESP系列模组在烧录固件时是按照要烧录的文件地址烧录对应文件的大小到flash,其他部分的 flash 未改动,

      例如 user1.bin 文件为 320K,从flash地址0x01000地址开始烧录,烧录320K字节,如果第二次烧录的时候,编译生成的 user1.bin 只有 300k,那么比对上一次烧录的user1.bin文件在flash中的存储,后面的20K falsh是不会擦除的。
      这样的烧录方式在大批量生产中是不安全的,尤其是有部分客户会在 flash 中添加自己的一些数据直接烧录进去。
      将所有的固件打包合并成一个完整的固件,烧录时会填充整个flash,对应地址没有程序部分的flash会被0xFF填充。

    详细见:官方文档《 ESP8266系列入门教程 esp8266_start_guide_1_v2.0.pdf 》第3.6节,固件合并说明。



其他说明

esp_init_data_default.bin文件版本说明

从1.6.2版本中,可以看到官方新增了 esp_init_data_default_v08.bin 文件。从GitHub更新日志看到如下解释:

Adjusted the default target power, from the 34th byte to the 39th byte of esp_init_data_default.bin,  lower the target power of each level, optimized the frequency spectrum Mask and the EVM.

翻译:调整默认目标电源,从esp_init_data_default.bin的第34个字节到第39个字节,降低各级目标功率,优化频谱掩码和EVM。

参考文档:



固件编译之NonOS固件

搭建编译环境

Windows下搭建

参考: 官方windows编译环境搭建教程

下载 IDE V1.5版本,安装好。



获取 NONOS SDK

git地址:

git clone https://gitee.com/xuhongv/ESP8266_NONOS_SDK

**注:**根目录下的driver_libthird_party这2个文件夹,可以不用删除。



编译工程

  • 先按照官方文档,导入工程文件。
  • 设置make参数,选择Properties --> C/C++ Build --> Build command 中添加编译规则,当前硬件是 32Mbit的模块,所以这样填:( make COMPILE=gcc BOOT=none APP=0 SPI_SPEED=40 SPI_MODE=DIO SPI_SIZE_MAP=6 );
  • example目录下的IoT_Demo文件夹复制到SDK的根目录,(编译AT固件就将at文件夹复制到SDK根目录)
  • 设置要编译的工程文件路径,在Properties --> C/C++ Build --> Build directory 选择编译的工程路径,比如根目录下的 IoT_Demo工程。
  • 右键工程,选择 编译工程 build Project,开始编译。

**注:**按照官方文档,基本上是一键编译成功。

ESP8266_NONOS_SDK 文件目录图(包含复制的at和IoT_Demo文件夹):

make相关参数含义

make COMPILE=gcc  BOOT=none  APP=0  SPI_SPEED=40  SPI_MODE=DOUT  SPI_SIZE_MAP=5
  • COMPILE=gcc 指定编译器,不用修改。

  • BOOT=none 指定boot版本,

    • none 无boot版本 (编译 Non-FOTA 选择此项)
    • old boot_v1.1
    • new boot_v1.2+ (编译 FOTA 选择此项)
  • APP=0 指定 系统程序bin的类型

    • 0 生成 eagle.flash.bin + eagle.irom0text.bin 文件 (Non-FOTA固件)
    • 1 生成 user1.bin (FOTA固件)
    • 2 生成 user2.bin
  • SPI_SPEED=40 指定和Flash通信的SPI速度(需要Flash支持)

    • 20 为 20MHz
    • 26.7 为 26.7MHz
    • 40 为 40MHz (默认40MHz)
    • 80 为 80MHz
  • SPI_MODE=DOUT 指定和Flash通信的SPI模式(需要Flash支持)

    • QIO Flash采用Quad SPI模式,地址为 4线模式输入,数据为 4线模式输出
    • QOUT Flash采用Quad SPI模式,地址为 1线模式输入,数据为 4线模式输出
    • DIO Flash采用Dual SPI模式,地址为 2线模式输入,数据为 2线模式输出
    • DOUT Flash采用Dual SPI模式,地址为 1线模式输入,数据为 2线模式输出(官方固件是DOUT模式,可选其他模式)

    **注:**ESP-12F模块支持的SPI模式:QIO,QOUT,DIO,DOUT,编译固件时设置的模式要和烧录时设置的模式统一。

    参考: 如何给 ESP32 选择外接 Flash 以及如何使能 QIO 模式

  • SPI_SIZE_MAP=5 指定spi_size和map映射

    • 0 = 512KB( 256KB+ 256KB)
    • 2 = 1024KB( 512KB+ 512KB)
    • 3 = 2048KB( 512KB+ 512KB)
    • 4 = 4096KB( 512KB+ 512KB)
    • 5 = 2048KB(1024KB+1024KB)
    • 6 = 4096KB(1024KB+1024KB) (32Mbit的Flash选择此项)
    • 7 = 4096KB(2048KB+2048KB) not support ,just for compatible with nodeMCU board
    • 8 = 8192KB(1024KB+1024KB)
    • 9 = 16384KB(1024KB+1024KB)

Flash烧录程序中对应的选项图:



IoT_Demo和AT固件编译说明

  1. 编译IoT_Demo固件,使用命令:
make COMPILE=gcc  BOOT=none  APP=0  SPI_SPEED=40  SPI_MODE=QIO  SPI_SIZE_MAP=6

build directory设置:

${workspace_loc:/ESP8266_NONOS_SDK}/IoT_Demo



  1. 编译AT固件,使用命令:

1)FOTA固件:

make COMPILE=gcc  BOOT=new  APP=1  SPI_SPEED=40  SPI_MODE=QIO  SPI_SIZE_MAP=6

2)NON-FOTA固件:

make COMPILE=gcc  BOOT=none  APP=0  SPI_SPEED=40  SPI_MODE=QIO  SPI_SIZE_MAP=6

build directory设置:

${workspace_loc:/ESP8266_NONOS_SDK}/at

注:
在编译AT的NON-FOTA固件时,最后的链接可能会出错,参考下文修改irom的大小即可。
https://blog.csdn.net/ydogg/article/details/72598777?locationNum=14&fps=1



编译RTOS固件

获取ESP8266 RTOS源码

官方地址:https://github.com/espressif/ESP8266_RTOS_SDK

设置环境变量和交叉编译工具

  1. 设置交叉编译工具

RTOS SDK V3.0 使用 V5.2.0版本的交叉编译工具。

RTOS SDK版本小于V3.0 使用 V4.8.5版本的交叉编译工具。

ubuntu下设置交叉编译工具的环境变量,这里就不介绍了。

  1. 设置IDF_PATH变量
export IDF_PATH=~/esp/ESP8266_RTOS_SDK

ESP8266_RTOS_SDK 目录路径根据自己情况填写。

编译一个hello项目

examples/get-started文件夹下,复制 hello_world文件夹到SDK根目录。

进入刚复制到SDK根目录下的hello_world 文件夹。

  1. 执行 make menuconfig,进入SDK配置,选择Serial flasher config 选项,设置串口和flash大小等。

然后保存,退出。

  1. 执行 make all,开始编译项目。

生成的镜像文件在hello_world/build目录下。

​ 图为 成功编译完成

  1. 执行make flash 烧写项目的镜像到ESP8266模块。

  2. 执行make monitor打开串口监视,读取RTOS固件输出的信息。

也可以用其他串口工具。



编译NodeMCU固件

获取NodeMCU固件

官方地址:https://github.com/nodemcu/nodemcu-firmware/



环境变量设置

NodeMCU在编译时,会自己下载交叉编译工具,和其他相关文件。

注意: 在编译NodeMCU时,关闭编译RTOS或NONOS的交叉编译工具环境配置。否则会出现编译失败。



编译NodeMCU固件

进入NodeMCU的根目录,执行make命令,第一次执行,会下载相关工具。

编译完成如下图:

生成的镜像文件在bin/ 目录下,如下图:

使用安信可提供的ESP8266烧录工具,设置好烧录地址即可烧录。



使用ESPlorer工具测试固件

工具下载地址:https://github.com/4refr0nt/ESPlorer

Windows下,双击ESPlorer.bat文件,即可打开。

左侧栏可以输入lua代码,发送到ESP模块执行。其他功能自行探索。

**注:**NodeMCU V3.0版本,有些API的使用方法做了改变,,具体参考官方文档。

官方文档地址:https://nodemcu.readthedocs.io/en/master/



NodeMCU读取DHT11模块的温湿度

在lua编程中用到pin的编号是NodeMCU开发板的编号,比如下图:

ESP8266引脚 NodeMCU引脚
GPIO16 D0
GPIO5 D1
...以此类推 ...

图片的参考文档: https://github.com/nodemcu/nodemcu-devkit-v1.0

读取DHT11模块的lua代码 (适用于NodeMCU SDK V3.0版本):

-- connect to WiFi access point (DO NOT save config to flash)
print("Connecting WIFI...")
wifi.setmode(wifi.STATION)
station_cfg={}
station_cfg.ssid = "SSID"
station_cfg.pwd  = "SSID_Password"
station_cfg.save = false
wifi.sta.config(station_cfg)

wifi.sta.connect()

-- get dht11 Temperature and Humidity function.
function mydht11()
	pin = 7
	status, temp, humi, temp_dec, humi_dec = dht.read11(pin)
	if status == dht.OK then
		-- Integer firmware using this example
		print(string.format("DHT Temperature:%d.%03d;Humidity:%d.%03d\r\n",
			  math.floor(temp),
			  temp_dec,
			  math.floor(humi),
			  humi_dec
		))

		-- Float firmware using this example
		print("DHT Temperature:"..temp..";".."Humidity:"..humi)

	elseif status == dht.ERROR_CHECKSUM then
		print( "DHT Checksum error." )
	elseif status == dht.ERROR_TIMEOUT then
		print( "DHT timed out." )
	end
end



local mytimer = tmr.create()
mytimer:alarm(1000, tmr.ALARM_AUTO, function() 
	if wifi.sta.getip() == nil then 
		print("IP unavaiable, Waiting...") 
	else
		mytimer:stop()
		print("Config done, IP is "..wifi.sta.getip())
		mydht11()
	end 
end)



参考文档

  • 官方文档:ESP8266_SDK入门指南 esp8266-sdk_getting_started_guide_cn.pdf
  • 官方文档:ESP8266_iot_demo指南 esp8266_non-os_sdk_iot_demo_guide_cn.pdf
  • 官方文档:ESP-12F 规格书 esp-12f_product_specification_zh_v1.0.pdf
  • 官方文档:ESP8266系列入门教程 esp8266_start_guide_1_v2.0.pdf
  • 官方文档:ESP8266AT指令集 esp8266_at_instruction_set_cn.pdf
  • 官方文档:ESP8266AT指令使用示例 esp8266_at_command_examples_cn.pdf

以上文档都在安信可官网下载:https://docs.ai-thinker.com/esp8266/docs



NonOS_AT_V1.7.4.0_4MB Flash的可用固件

最后附上(内含烧录配置图,ESP-12F Flash为32Mbit的固件):

  1. 合成的单文件bin固件:https://files.cnblogs.com/files/wybliw/NonOS_AT_V1.7.4.0_4MB_single.zip
  2. 未合成的多文件bin固件:https://files.cnblogs.com/files/wybliw/NonOS_AT_V1.7.4.0_4MB_multi.zip



NodeMCU_integer_V3.0.0-master 4MB Flash的可用固件

(内含烧录配置图)

  1. 合成的单文件bin固件:https://files.cnblogs.com/files/wybliw/NodeMCU_integer_V3.0.0-master_20200610-DIO.bin.zip

== end ==

posted on 2020-07-26 21:50  wybliw  阅读(6207)  评论(0编辑  收藏  举报