当前位置: 首页 > news >正文

ESP8266固件升级分区表错误:手动烧录解决与esptool.py实战

1. 项目概述:当ESP8266固件升级“翻车”时

搞嵌入式开发,尤其是玩ESP8266这类Wi-Fi模块的朋友,估计都遇到过固件升级这个坎。模块买回来,兴冲冲地接上串口,打开图形化烧录工具,选好固件,一点“开始”,进度条跑得飞快,感觉一切顺利。结果一复位,串口监视器里蹦出来的不是熟悉的“ready”,而是一堆乱码,或者干脆没反应,只有板载的蓝色LED在疯狂闪烁。这时候的心情,就像精心搭好的积木被一脚踢散—— frustration 这个词,用在这里再贴切不过了。

我最近就栽在了给一块ESP-01S模块升级最新AT固件上。我的目标很明确:把模块自带的陈旧AT指令集(版本低到1.1.0.0)升级到最新的稳定版(1.7.5.0,基于Non-OS SDK 3.0.5),以确保更好的兼容性和稳定性。然而,图形化工具(比如乐鑫官方的Flash Download Tool)的“自动检测”功能,这次成了罪魁祸首。它把我的模块闪存识别成了32Mbit(4MB),并据此生成了分区表。但实际烧录后,模块启动时却报出“system param partition error”和“partition table size is larger than flash size”的错误。本质上,这就是一个典型的分区表配置错误:工具以为闪存很大,画了一张超出实际物理边界的地图,系统按图索骥时自然就“撞墙”了。

这个问题的核心,在于ESP8266启动过程中对闪存布局的严格依赖。固件并非简单的一整块数据,而是由引导程序(bootloader)、应用程序(如AT固件)、系统参数区等多个部分,按照一个称为“分区表”的蓝图,精确放置在闪存的不同地址上。如果这个蓝图(分区表)指示的某个分区地址,超出了闪存芯片的实际物理容量,系统在初始化时就会失败。而图形化工具的自动检测,在面对市面上五花八门的ESP8266模块(尤其是ESP-01这种封装小、型号杂的)时,并不总是可靠。

因此,本文将彻底抛弃对图形化工具自动检测的依赖,转向更底层、更可控的命令行工具——esptool.py。我们将手动指定闪存大小和每个固件文件的烧录地址,像一位精准的外科医生,将代码“缝合”到正确的位置。这个过程不仅解决了眼前的分区表错误,更能让你深刻理解ESP8266的存储结构,为日后更复杂的项目(如OTA升级、多固件切换)打下坚实基础。

2. 核心问题深度剖析:分区表错误的根源与表现

在动手修复之前,我们必须先当一回“侦探”,把分区表错误这个案子的来龙去脉搞清楚。这不仅仅是解决一次烧录失败,更是理解ESP8266系统架构的关键。

2.1 闪存、分区表与启动流程

你可以把ESP8266的闪存(Flash)想象成一本厚厚的书。这本书有固定的总页数(闪存容量,如1MB)。这本书的目录就是分区表,它规定了哪几页是前言(bootloader),哪几页是第一章(应用程序固件),哪几页是附录(系统参数、RF校准数据等)。

当ESP8266上电或复位时,第一段执行的代码是固化在芯片内部的ROM。这段ROM代码会去闪存最开始的固定位置(通常是0x0地址)读取二级引导程序。这个引导程序的任务之一,就是根据分区表的信息,找到应用程序的入口地址并跳转执行。如果分区表本身是错的——比如它说“第一章从第900页开始”,但这本书总共只有800页——那么引导程序在寻址时就会发生错误,系统自然无法正常启动。

2.2 错误日志的解读

当升级失败后,如果你将串口终端波特率调整为74880(这是ESP8266上电时打印调试信息的默认波特率),通常会看到类似下面的信息:

ets Jan 8 2013,rst cause:2, boot mode:(3,6) ... SPI Flash Size & Map: 4Mbit(256KB+256KB) jump to run user1 @ 1000 correct flash map mismatch map 2,spi_size_map 0 system param partition error --- The partition table size is larger than flash size 0x80000 --- please check partition type 6 addr:fd000 len:3000 system_partition_table_regist fail

这段日志是破案的关键线索:

  1. SPI Flash Size & Map: 4Mbit(256KB+256KB):系统检测到的闪存映射模式。这里的“4Mbit”容易让人误解,它指的是SPI闪存的一种工作模式(容量映射方式),而非绝对容量。spi_size_map 0对应一种具体的映射关系。
  2. mismatch map 2,spi_size_map 0:这里出现了不匹配。可能分区表是按map 2(对应另一种容量,如2MB)生成的,但实际硬件是map 0的模式。
  3. The partition table size is larger than flash size 0x80000:这是最直接的错误。0x80000是十六进制,转换为十进制是 524,288 字节,即512KB。错误提示明确指出,分区表要求的总空间超出了闪存的实际大小(512KB)。
  4. please check partition type 6 addr:fd000 len:3000:它甚至告诉你是哪个分区出了问题。地址0xfd000,换算成十进制是 1,036,288 字节(约1012KB)。对于一个只有512KB的闪存来说,这个地址显然是非法的。

注意:这里存在一个极大的迷惑点。图形化工具可能显示检测到“32Mbit(4MB)”,而错误日志又提到“4Mbit”和“512KB”。这通常是因为:工具错误识别了闪存ID,报告了错误的容量;而芯片启动时,是根据实际连接的硬件信号判断出的真实映射模式。两者冲突,导致了分区表配置的灾难性错误。

2.3 为何图形化工具会失败?

市面上的ESP-01/ESP-01S模块,为了降低成本,使用的闪存芯片型号繁杂。虽然很多模块标称4MB(32Mbit),但有些批次或廉价版本可能只搭载了1MB甚至512KB的闪存。图形化烧录工具通过读取闪存芯片的JEDEC ID来识别容量,但某些芯片的ID可能未被工具数据库正确收录,或者模块电路设计导致识别信号不标准,从而引发误判。

此外,即使是容量识别正确,工具内置的“默认”或“自动”分区方案也可能不适用于特定的AT固件版本。AT固件对分区布局有特定要求,尤其是esp_init_data_default.bin(RF初始化数据)和空白区域的位置,必须精确对应。

3. 解决方案与工具准备:放弃GUI,拥抱命令行

既然自动检测靠不住,我们就采用绝对可控的手动方式。这就需要请出我们今天的主角:esptool.py

3.1 为什么是 esptool.py?

esptool.py是乐鑫官方开源并维护的一个Python脚本,它是与ESP系列芯片(包括ESP8266、ESP32等)底层Bootloader通信的瑞士军刀。相比于图形化工具,它的优势在于:

  • 精确控制:可以明确指定每一个二进制文件烧录的起始地址和闪存大小参数,绕过自动检测。
  • 脚本化与自动化:可以写入脚本,便于批量操作或集成到CI/CD流程中。
  • 更丰富的功能:除了烧录,还能读取闪存、擦除区域、读取芯片ID、改变波特率等,是高级调试的利器。
  • 跨平台:只要有Python环境,Windows、macOS、Linux都能运行。

3.2 准备工作清单

在开始手术前,请确保你准备好了所有“手术器械”:

  1. 硬件连接

    • ESP-01/ESP-01S模块一个。
    • USB转串口(TTL)编程器一个。强烈建议使用带有DTR和RTS自动复位电路的型号(如CP2102、CH340、FT232RL芯片的),这可以让你免去手动连接EN/GPIO0进行进入下载模式的麻烦。
    • 连接线:确保编程器的3.3V(或5V,取决于模块)、GND、TX、RX与ESP模块正确连接。特别注意:ESP8266是3.3V器件,确保编程器VCC输出为3.3V,否则可能损坏模块!
  2. 软件与环境准备

    • Python 3:前往Python官网下载并安装。安装时务必勾选“Add Python to PATH”选项,这能让你在命令行中直接使用pythonpip命令。
    • esptool.py:有两种方式安装:
      • (推荐)通过pip安装:打开命令行(Windows CMD/PowerShell, macOS/Linux Terminal),输入pip install esptool。安装完成后,直接在命令行输入esptool.pyesptool应能看到帮助信息。
      • 手动下载:从GitHub仓库下载源码包,解压后,在解压目录中运行python esptool.py。但这种方式管理依赖不太方便。
    • 最新AT固件文件:我们需要乐鑫官方发布的Non-OS SDK AT固件包。你可以从乐鑫的GitHub Release页面或官方论坛找到ESP8266_NONOS_SDK-3.0.5(或更新版本)。下载后解压。

3.3 获取正确的固件文件

解压ESP8266_NONOS_SDK-3.0.5后,关键的文件在bin/目录下。但AT固件有专门的位置。我们需要以下文件,请根据你的模块闪存大小进行选择:

对于 1MB (8Mbit) 闪存的模块(最常见): 所需文件位于ESP8266_NONOS_SDK-3.0.5/bin/at/512+512/目录下。

  • boot_v1.7.bin- 引导程序
  • user1.1024.new.2.bin- 主AT固件应用程序(注意:文件名中的1024指1024KB,即1MB)
  • esp_init_data_default_v08.bin- RF射频初始化数据,对Wi-Fi性能至关重要
  • blank.bin- 空白数据文件,用于擦除特定区域

对于 512KB (4Mbit) 闪存的模块: 所需文件位于ESP8266_NONOS_SDK-3.0.5/bin/at/256+256/目录下。

  • boot_v1.6.bin- 注意引导程序版本可能不同
  • user1.512.new.2.bin- 主AT固件(512KB版本)
  • esp_init_data_default_v08.bin
  • blank.bin

对于 2MB (16Mbit) 或更大闪存的模块: 可以使用512+512的固件,也可以使用1024+1024(如果目录存在)的固件,后者可能包含更多功能。但地址映射需要调整。

实操心得:如何确定模块的真实容量?这是最关键的一步。如果模块本身没有明确标注,可以尝试以下方法:

  1. 查看芯片型号:仔细查看闪存芯片上的丝印,常见型号如:W25Q40BV(512KB)、W25Q80BV(1MB)、W25Q16BV(2MB)、W25Q32BV(4MB)。最后几位数字通常代表容量(40=4Mbit/512KB, 80=8Mbit/1MB, 16=16Mbit/2MB, 32=32Mbit/4MB)。
  2. 使用esptool.py检测:连接好模块并进入下载模式(GPIO0拉低后复位),在命令行运行:esptool.py --port COMx flash_id(Windows)或esptool.py --port /dev/ttyUSBx flash_id(Linux/macOS)。在输出信息中查找Detected flash size:这一行,这里的值相对更可靠。
  3. 经验判断:市面上大量的ESP-01S模块标配是1MB。如果你从上述512+512256+256两个目录的固件都试过且地址正确仍报错,可以怀疑是1MB的。

我将以最常见的1MB 闪存模块为例,进行后续的烧录操作。请将你选定的四个.bin文件(boot_v1.7.bin,user1.1024.new.2.bin,esp_init_data_default_v08.bin,blank.bin)复制到一个单独的、干净的文件夹中,方便操作。

4. 使用esptool.py进行手动精确烧录

现在进入最核心的实操环节。我们将放弃所有图形界面,完全通过命令行来控制烧录过程。

4.1 进入下载模式

ESP8266必须进入“下载模式”才能接收新的固件。对于ESP-01/ESP-01S:

  1. 确保模块未通电。
  2. 将编程器的GPIO0引脚(或对应跳线)连接到ESP模块的GPIO0引脚。
  3. 将编程器的GND连接到ESP模块的GND。
  4. 将GPIO0拉低(即连接到GND)。
  5. 然后给模块上电(插入USB)。
  6. 此时,模块应进入下载模式。如果编程器带自动下载电路(DTR/RTS控制),通常只需确保GPIO0在电路中被正确控制,甚至无需手动操作,工具会自动触发。

4.2 烧录命令详解

打开命令行(终端),使用cd命令切换到存放你所有.bin文件的目录。然后执行烧录命令。命令的通用格式如下:

esptool.py --port <串口号> --baud <波特率> write_flash --flash_size <闪存大小> <地址1> <文件1> <地址2> <文件2> ...

对于1MB闪存,烧录最新AT固件的完整命令是:

esptool.py --port COM3 --baud 115200 write_flash --flash_size 1MB 0x0 boot_v1.7.bin 0x01000 user1.1024.new.2.bin 0xfb000 blank.bin 0xfc000 esp_init_data_default_v08.bin 0xfe000 blank.bin 0x7e000 blank.bin

让我们拆解这个命令的每一个部分:

  • --port COM3:指定串口号。在Windows上,通常是COM3COM4等,可以在设备管理器中查看。在Linux/macOS上,通常是/dev/ttyUSB0/dev/ttyACM0请务必替换成你的实际端口号!
  • --baud 115200:设置与Bootloader通信的波特率。115200是可靠的标准速率,如果遇到问题可以尝试降低到960057600
  • write_flash:子命令,表示执行写闪存操作。
  • --flash_size 1MB这是解决分区表错误的关键!我们手动告诉esptool.py,目标闪存是1MB容量。这会确保工具内部使用正确的分区映射(spi_size_map),从而生成正确的分区信息。如果你的模块是512KB,这里应改为512KB;2MB则改为2MB
  • 0x0 boot_v1.7.bin:将引导程序烧录到闪存的起始地址0x0
  • 0x01000 user1.1024.new.2.bin:将主AT应用程序烧录到地址0x1000(十进制4096)。这是SDK规定的应用程序起始地址。
  • 0xfb000 blank.bin:在地址0xFB000处写入空白数据。这个地址是RF校准参数区的一部分,先擦除(写入blank)以确保干净。
  • 0xfc000 esp_init_data_default_v08.bin:将RF初始化数据烧录到0xFC000。这个文件包含了Wi-Fi射频电路的校准参数,对于信号强度和质量至关重要。
  • 0xfe000 blank.bin:在地址0xFE000处写入空白数据。这是系统参数区的末尾,擦除以确保旧数据被清除。
  • 0x7e000 blank.bin:在地址0x7E000处写入空白数据。这个地址对应的是“系统参数区”的起始区域(对于1MB映射)。烧录blank.bin是为了擦除该区域可能存在的旧分区表或其他配置数据。

重要提示:这些地址(0x7e000,0xfb000,0xfc000,0xfe000)是乐鑫为1MB闪存、使用“512+512”AT固件所定义的特定分区布局。对于不同容量或不同固件,这些地址会变化。这就是为什么不能盲目使用图形化工具默认设置的原因。

4.3 执行烧录与验证

  1. 在命令行中粘贴修改好端口号的命令,按回车执行。

  2. 如果模块连接正确且处于下载模式,你将看到类似下面的输出:

    Connecting........__ Detecting chip type... ESP8266 Chip is ESP8266EX Features: WiFi Crystal is 26MHz MAC: xx:xx:xx:xx:xx:xx Uploading stub... Running stub... Stub running... Configuring flash size... Compressed 4096 bytes to 29... Writing at 0x00000000... (100 %) Wrote 4096 bytes (29 compressed) at 0x00000000 in 0.0 seconds (effective 5461.3 kbit/s)... Hash of data verified. Compressed 1024512 bytes to 675625... Writing at 0x00001000... (16 %) Writing at 0x00005000... (33 %) ... (进度会持续更新) Leaving... Hard resetting via RTS pin...
  3. 烧录过程可能会持续一两分钟,请耐心等待。所有文件写入并校验成功后,工具会尝试通过拉低RTS线(如果连接了)来自动复位模块。

  4. 验证:烧录完成后,断开GPIO0与GND的连接(如果是手动连接的),或直接给模块重新上电。打开串口终端软件(如Putty、Arduino IDE串口监视器、CoolTerm等),设置波特率为115200(这是AT指令通信的标准波特率),数据位8,停止位1,无校验。复位模块,你应该看到类似以下的启动信息:

    ets Jan 8 2013,rst cause:1, boot mode:(3,0) 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

    几秒后,最关键的标志出现了:

    ready

    看到“ready”,恭喜你!这表示ESP8266已经成功启动最新的AT固件,正在等待你的指令。

  5. 测试AT指令:在串口终端中,输入AT并回车。模块应回复OK。再输入AT+GMR查看版本信息,你应该能看到类似AT version:1.7.5.0(......)SDK version:3.0.5的输出,这证实了固件已成功升级到最新版本。

5. 故障排查与深度优化指南

即使按照上述步骤操作,你可能还是会遇到一些问题。这里汇总了常见的坑和解决方案。

5.1 常见错误与解决方法

问题现象可能原因排查与解决步骤
Failed to connect to ESP82661. 串口号错误。
2. 模块未进入下载模式。
3. 波特率过高。
4. 驱动未安装或USB线接触不良。
1. 检查设备管理器,确认端口号。
2. 确保上电前GPIO0已稳定接GND。对于自动下载电路,检查DTR/RTS接线。
3. 尝试在命令中添加--baud 9600使用更低波特率连接。
4. 重新插拔USB,安装CH340/CP2102驱动。
A fatal error occurred: Failed to write flash1. 闪存容量参数--flash_size设置错误。
2. 烧录地址错误,超出物理闪存范围。
3. 闪存芯片已损坏。
1. 用esptool.py flash_id命令再次确认容量,并修正--flash_size参数。
2. 核对本文给出的地址是否适用于你的固件版本和容量。对于512KB模块,地址完全不同。
3. 尝试先擦除整个闪存:esptool.py erase_flash,然后再烧录。
烧录成功,但启动后仍报分区错误1.--flash_size参数在烧录时未生效或指定错误。
2.blank.bin未正确烧录到系统参数区,旧分区表残留。
3. 使用了错误版本的固件文件(如为1MB模块用了256+256的固件)。
1. 确保命令中--flash_size参数在write_flash之后。
2. 确保0x7e0000xfe000地址确实烧录了blank.bin
3. 重新从SDK包中获取对应容量的固件文件。
启动后无“ready”或AT无响应1. 串口终端波特率未设置为115200。
2. 固件烧录不完整或损坏。
3.esp_init_data_default.bin未烧录或地址错误,导致RF初始化失败。
1. 确认终端波特率为115200。
2. 重新烧录,确保每个步骤都成功完成。
3. 对于1MB模块,务必确保esp_init_data_default_v08.bin烧录在0xfc000
能收到“ready”,但Wi-Fi无法连接1.esp_init_data_default.bin数据问题或地址不对。
2. 天线未连接或损坏(对于ESP-01)。
1. 尝试从SDK的bin根目录(而非at子目录)下复制一个esp_init_data_default.bin(可能是v05版本)到0xfc000试试。不同版本SDK的RF数据可能有优化。
2. 检查ESP-01的板载天线或外接天线连接。

5.2 针对不同容量模块的地址调整

本文给出的地址是针对1MB (8Mbit) 闪存,使用512+512AT固件。如果你的模块容量不同,绝对不能照搬这些地址。以下是调整指南:

  • 对于512KB (4Mbit) 模块,使用256+256固件: 常见的地址布局可能是:0x0 boot_v1.6.bin0x01000 user1.512.new.2.bin0x7c000 esp_init_data_default_v08.bin0x7e000 blank.bin0x3e000 blank.bin注意:这只是一个示例,最准确的做法是查阅你所使用的SDK版本中at目录下的readme.mdflash_download.md文件,里面会给出官方推荐的烧录地址。

  • 对于2MB (16Mbit) 或 4MB (32Mbit) 模块: 你可以继续使用512+512的固件,因为1MB的固件可以烧录在更大闪存的前端。地址可以保持不变。但如果你想利用多余的空间(例如用于文件系统SPIFFS),则需要使用对应的1024+1024固件并调整地址,这通常涉及自定义分区表,属于更进阶的操作。

5.3 高级技巧:创建一键烧录脚本

如果你需要频繁为同型号模块烧录固件,每次都输入长命令很麻烦。可以创建一个脚本文件。

在Windows上

  1. 新建一个文本文件,命名为flash_firmware.bat
  2. 用记事本编辑,内容如下:
    @echo off esptool.py --port COM3 --baud 115200 write_flash --flash_size 1MB ^ 0x0 boot_v1.7.bin ^ 0x01000 user1.1024.new.2.bin ^ 0xfb000 blank.bin ^ 0xfc000 esp_init_data_default_v08.bin ^ 0xfe000 blank.bin ^ 0x7e000 blank.bin pause
  3. COM3改为你的端口号,并将此bat文件放在所有.bin文件的同一目录下。双击即可运行。

在macOS/Linux上

  1. 新建一个文本文件,命名为flash_firmware.sh
  2. 编辑内容:
    #!/bin/bash esptool.py --port /dev/ttyUSB0 --baud 115200 write_flash --flash_size 1MB \ 0x0 boot_v1.7.bin \ 0x01000 user1.1024.new.2.bin \ 0xfb000 blank.bin \ 0xfc000 esp_init_data_default_v08.bin \ 0xfe000 blank.bin \ 0x7e000 blank.bin
  3. 在终端中,进入该目录,运行chmod +x flash_firmware.sh赋予执行权限,然后运行./flash_firmware.sh

5.4 彻底擦除与救砖

如果模块处于一种完全无法识别或任何固件都无法启动的状态(俗称“砖了”),可以尝试强制擦除整个闪存:

esptool.py --port COM3 erase_flash

执行完毕后,再重新进行完整的烧录流程。这能清除所有错误的分区表和残留数据,相当于给闪存做了一次格式化。

经过以上步骤,你应该已经成功地将ESP8266模块从分区表错误的困境中解救出来,并为其注入了最新的AT固件。这个过程虽然比点击图形界面按钮复杂,但它赋予了你对嵌入式系统底层烧录过程的完全掌控力。下次再遇到类似的升级问题,你完全可以淡定地打开命令行,用几行精准的指令解决问题。记住,在嵌入式开发中,知其然并知其所以然,是摆脱依赖、走向精通的必经之路。

http://www.jsqmd.com/news/931795/

相关文章:

  • Qwen2.5-14B-Instruct-8bit进阶技巧:提示工程优化与模型输出质量控制方法
  • 人工智能驱动 DevOps 工具:加速软件开发全生命周期,缩短周期时间 20% - 40%
  • AI 眼镜热闹背后存隐忧:功能虽多,用户痛点待解,品类成熟需先“克制”
  • 5分钟掌握终极视频修复术:用untrunc快速恢复损坏的MP4/MOV文件
  • 5个核心技术突破:ExtractorSharp专业级游戏资源编辑器实战指南
  • CANN/ops-blas Sdot算子实现
  • roberta-base-go-emotions:革命性28维情感AI模型,让机器读懂人类情感
  • 如何永久保存微信聊天记录:WeChatMsg终极数据留痕解决方案
  • Windows 11界面改造神器:ExplorerPatcher完整使用指南
  • OpCore-Simplify:从复杂到简单的黑苹果配置终极解决方案
  • social-auto-upload案例研究:企业级社交媒体自动化方案
  • CentOS 10 nmcli命令 如何找到 虚拟接口
  • 终极指南:如何选择最适合你的DrakeTyporaTheme十二款Typora主题
  • 2026漳州卫生间免砸砖防水、外墙、地下室、楼顶渗漏+彩钢瓦、阳光房漏水 本地专业防水公司TOP5权威推荐(2026年6月本地最新深度调研) - 企业资讯
  • 家庭WiFi网络全面优化指南:从硬件选购到配置调优
  • 以撒结合REPENTOGON脚本扩展器:从零开始解锁模组开发新纪元
  • 从一次右键卸载失败,聊聊银河麒麟V10的软件包管理“暗桩”
  • Trelby:为什么这款免费开源剧本写作软件能让你专注于故事创作?
  • 手把手教你用Python处理Weibo_datasets虚假新闻检测数据集(含图片爬虫与数据清洗)
  • 【Sora 2视频制作黄金法则】:20年AIGC专家首曝3大避坑步骤、5类必调参数与实时渲染提速87%的私藏工作流
  • Ubuntu系统盘突然爆满?别慌,先检查一下这些/dev/loop设备
  • 长龙洗碗机高效方案,瑞宝厨具赋能商用厨房 - 资讯焦点
  • 霞鹜文楷:开源中文字体在跨语言排版中的技术实践
  • TransmonCross Hamiltonian to Geometry API详解:完整接口文档与使用示例
  • 如何用录播姬轻松录制mikufans直播:完整使用指南
  • 如何轻松下载国家中小学智慧教育平台的电子课本?tchMaterial-parser工具详解
  • 如何选择适合的切削液品牌? - 资讯焦点
  • Citra 3DS模拟器:如何在Windows、macOS和Linux上畅玩任天堂3DS游戏
  • 告别模糊CT图:用Python手把手实现SART算法,从投影数据重建清晰图像
  • 黑苹果配置革命:10分钟自动化完成OpenCore EFI配置的终极指南