AM335x uboot中Nand Flash调试

2023-12-14 16:59
文章标签 uboot 调试 flash nand am335x

本文主要是介绍AM335x uboot中Nand Flash调试,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

目前手头有两块AM335x的板子,硬件上除了nand flash型号不同外,其它硬件状态相同。u-boot版本2019.01,为了方便NAND的调试,需要提前先把SDCard引导启动调通,然后在从SDCard启动,这里先不用kernel,直接在uboot中来测试NAND flash的读写。
  另外如果要想从NAND中启动uboot,还需要硬件上设置sysboot可以从NAND引导。sysboot详情可以参见《AM335x and AMIC110 Sitara™ Processors.pdf》的SYSBOOT Configuration Pins章节,主要是sysboot[9],sysboot[4:0]。
  1.修改pinmux并在初始化时调用gpmc_init(),修改位于board.c和mux.c中,再就是根据情况添加所需要的宏。
mux.c

/*定义引脚功能*/
#ifdef CONFIG_NANDstatic struct module_pin_mux nand_pin_mux[] = {{OFFSET(gpmc_ad0),      (MODE(0) | PULLUDDIS | RXACTIVE)}, /* AD0  */{OFFSET(gpmc_ad1),      (MODE(0) | PULLUDDIS | RXACTIVE)}, /* AD1  */{OFFSET(gpmc_ad2),      (MODE(0) | PULLUDDIS | RXACTIVE)}, /* AD2  */{OFFSET(gpmc_ad3),      (MODE(0) | PULLUDDIS | RXACTIVE)}, /* AD3  */{OFFSET(gpmc_ad4),      (MODE(0) | PULLUDDIS | RXACTIVE)}, /* AD4  */{OFFSET(gpmc_ad5),      (MODE(0) | PULLUDDIS | RXACTIVE)}, /* AD5  */{OFFSET(gpmc_ad6),      (MODE(0) | PULLUDDIS | RXACTIVE)}, /* AD6  */{OFFSET(gpmc_ad7),      (MODE(0) | PULLUDDIS | RXACTIVE)}, /* AD7  */
#ifdef CONFIG_SYS_NAND_BUSWIDTH_16BIT{OFFSET(gpmc_ad8),      (MODE(0) | PULLUDDIS | RXACTIVE)}, /* AD8  */{OFFSET(gpmc_ad9),      (MODE(0) | PULLUDDIS | RXACTIVE)}, /* AD9  */{OFFSET(gpmc_ad10),     (MODE(0) | PULLUDDIS | RXACTIVE)}, /* AD10 */{OFFSET(gpmc_ad11),     (MODE(0) | PULLUDDIS | RXACTIVE)}, /* AD11 */{OFFSET(gpmc_ad12),     (MODE(0) | PULLUDDIS | RXACTIVE)}, /* AD12 */{OFFSET(gpmc_ad13),     (MODE(0) | PULLUDDIS | RXACTIVE)}, /* AD13 */{OFFSET(gpmc_ad14),     (MODE(0) | PULLUDDIS | RXACTIVE)}, /* AD14 */{OFFSET(gpmc_ad15),     (MODE(0) | PULLUDDIS | RXACTIVE)}, /* AD15 */
#endif{OFFSET(gpmc_wait0),    (MODE(0) | PULLUP_EN | RXACTIVE)}, /* nWAIT */{OFFSET(gpmc_wpn),      (MODE(7) | PULLUP_EN)},            /* nWP */{OFFSET(gpmc_csn0),     (MODE(0) | PULLUP_EN)},            /* nCS */{OFFSET(gpmc_wen),      (MODE(0) | PULLDOWN_EN)},          /* WEN */{OFFSET(gpmc_oen_ren),  (MODE(0) | PULLDOWN_EN)},          /* OE */{OFFSET(gpmc_advn_ale), (MODE(0) | PULLDOWN_EN)},          /* ADV_ALE */{OFFSET(gpmc_be0n_cle), (MODE(0) | PULLDOWN_EN)},          /* BE_CLE */{-1},
};
#endif/*中间代码省略*/void enable_board_pin_mux(void)
{
//	configure_module_pin_mux(rgmii1_pin_mux);configure_module_pin_mux(mmc0_pin_mux);
#if defined(CONFIG_NAND)configure_module_pin_mux(nand_pin_mux);
#elseconfigure_module_pin_mux(mmc1_pin_mux);
#endif}

board.c

/*board_init中添加对gpmc_init调用*/
/** Basic board specific setup.  Pinmux has been handled already.*/
int board_init(void)
{
#if defined(CONFIG_HW_WATCHDOG)hw_watchdog_init();
#endifgd->bd->bi_boot_params = CONFIG_SYS_SDRAM_BASE + 0x100;
#if defined(CONFIG_NOR) || defined(CONFIG_NAND)gpmc_init();    
#endifreturn 0;
}

配置相关的宏,这里面整理一下NAND中可能会用到的宏。

CONFIG_CMD_SPL_NAND_OFS=0x00080000
CONFIG_CMD_NAND=y
CONFIG_ENV_IS_IN_NAND=y
CONFIG_MTDPARTS_DEFAULT="mtdparts=nand.0:512k(NAND.SPL),512k(NAND.SPL.backup1),512k(NAND.SPL.backup2),512k(NAND.SPL.backup3),2m(NAND.u-boot),1m(NAND.u-boot-env),1m(NAND.u-boot-spl-os),8m(NAND.kernel),-(NAND.file-system)"
CONFIG_DFU_NAND=y
CONFIG_NAND=y
CONFIG_NAND_BOOT=y						//没有这个宏无法从NAND引导启动,刚开始没配置导致折腾了半天才发现这个问题。
CONFIG_SPL_NAND_SUPPORT=y
CONFIG_LZO=y

修改头文件,配置NAND参数:

#define CONFIG_SYS_NAND_PAGE_SIZE	2048
#define CONFIG_SYS_NAND_OOBSIZE		64
#define CONFIG_SYS_NAND_BLOCK_SIZE	(128*1024)/* NAND: driver related configs */
#define CONFIG_SYS_NAND_BAD_BLOCK_POS	NAND_LARGE_BADBLOCK_POS
#define CONFIG_SYS_NAND_ECCPOS		{ 2, 3, 4, 5, 6, 7, 8, 9, \10, 11, 12, 13, 14, 15, 16, 17, \18, 19, 20, 21, 22, 23, 24, 25, \26, 27, 28, 29, 30, 31, 32, 33, \34, 35, 36, 37, 38, 39, 40, 41, \42, 43, 44, 45, 46, 47, 48, 49, \50, 51, 52, 53, 54, 55, 56, 57, }#define CONFIG_SYS_NAND_ECCSIZE		512
#define CONFIG_SYS_NAND_ECCBYTES	14
#define CONFIG_SYS_NAND_ONFI_DETECTION
#define CONFIG_NAND_OMAP_ECCSCHEME      OMAP_ECC_BCH8_CODE_HW
#endif
#define CONFIG_SYS_NAND_U_BOOT_OFFS	0x00200000
/* NAND: SPL related configs */
#ifdef CONFIG_SPL_OS_BOOT
#define CONFIG_SYS_NAND_SPL_KERNEL_OFFS	0x00600000 /* kernel offset */
#endif
#endif /* !CONFIG_NAND */

2.重新编译uboot将MLO和u-boot.img烧写到SDCard中,设置从SDCard启动uboot,在uboot的命令行中输入mtdparts来查看nand的分区情况,对比下分区信息应该和CONFIG_MTDPARTS_DEFAULT宏中定义的分区信息相同。其次就是利用nand命令查看nand信息和测试nand读写是否正常,如果提示什么ECC 错误可以尝试把整个芯片擦除一下重新写(如果还是不行后面找答案),下面列出几个nand命令,其它的可以参考nand的帮助信息。

/*写MLO文件到NAND中*/
fatload mmc 0:1 82000000 MLO;
nand erase.part NAND.SPL;
nand write 82000000 NAND.SPL 80000;
/*写u-boot.img文件NAND中*/
fatload mmc 0:1 82000000 u-boot.img;
nand erase.part NAND.u-boot;
nand write 82000000 NAND.u-boot 100000;

3.可以利用上面的命令将MLO文件和u-boot.img烧写到相应的nand分区。烧写完成后设置sysboot从nand引导启动一下看能不能启动起来,如果不行参考下面的介绍在继续修改。
  文初提到手头有两块NAND型号不同的板子,起初调试用的是ti划分的分区( CONFIG_MTDPARTS_DEFAULT=“mtdparts=nand.0:128k(NAND.SPL),128k(NAND.SPL.backup1),128k(NAND.SPL.backup2),128k(NAND.SPL.backup3),256k(NAND.u-boot-spl-os),1m(NAND.u-boot),128k(NAND.u-boot-env),128k(NAND.u-boot-env.backup1),8m(NAND.kernel),-(NAND.file-system)”
),其中一块的NAND型号MX60LF8G18AC已经可以正常启动了。但是另一块NAND型号MT29F8G08ABABAWP就一直无法启动,串口打印“CCCC”。并且用mtdparts查看分区时提示“nand0: partition (NAND.SPL) size alignment incorrect”。对比两个芯片的手册发现:MX60LF8G18AC的 page size:(2048+64)byte Block size:(128K+4K)byte 而MT29F8G08ABABAWP的page size:(4096+224)byte Block size:(512K+28K)byte,可以看到两个芯片的block size是不同的,在nand中最小的操作单元是block,显然这个128k的分区不能满足MT29F8G08ABABAWP中block是512K的要求,所以需要调整所有分区大小使同时满足128K和512K的整数倍,这样的话就可以同时支持两种型号的NAND。

nand0: partition (NAND.SPL) size alignment incorrect
  因为CONFIG_MTDPARTS_DEFAULT的分区信息做了调整,所以u-boot.img,环境变量、内核等的存放地址也发生了变化,在头文件中也需要做相应的调整;下面代码中后面的地址如果不想自己算的话,可以先编译烧写SDCard中利用mtdparts查看。

#define CONFIG_SYS_NAND_U_BOOT_OFFS     0x00100000   //u-boot.img的偏移地址(NAND.u-boot)
#define CONFIG_SYS_NAND_SPL_KERNEL_OFFS 0x00500000 		//* kernel offset(NAND.kernel) */
#define CONFIG_ENV_OFFSET               0x00300000       //环境变量存放位置

其次因两个NAND的分页和块信息不一样,所以头文件中的NAND参数也要做相应改动。下面是两种nand的修改后的参数:

#ifdef CONFIG_NAND
/* NAND: device related configs */
#define CONFIG_SYS_NAND_5_ADDR_CYCLE
#define CONFIG_SYS_NAND_PAGE_COUNT	(CONFIG_SYS_NAND_BLOCK_SIZE / \CONFIG_SYS_NAND_PAGE_SIZE)
#ifdef CONFIG_NAND_MT29F8G08ABABAWP   //自己添加的宏,需要用时请在Kconfig和deconfig中增加。
/*MT29F8G08ABABAWP配置*/
#define CONFIG_SYS_NAND_PAGE_SIZE       4096
#define CONFIG_SYS_NAND_OOBSIZE         224
#define CONFIG_SYS_NAND_BLOCK_SIZE      (512*1024)
/* NAND: driver related configs */
#define CONFIG_SYS_NAND_BAD_BLOCK_POS   NAND_LARGE_BADBLOCK_POS
#define CONFIG_SYS_NAND_ECCPOS  { 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,\16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, \28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39,\40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51,\52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,\64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75,\76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87,\88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99,\100, 101, 102, 103, 104, 105, 106, 107, 108, 109,\110, 111, 112, 113, 114, 115, 116, 117, 118, 119,\120, 121, 122, 123, 124, 125, 126, 127, 128, 129,\130, 131, 132, 133, 134, 135, 136, 137, 138, 139,\140, 141, 142, 143, 144, 145, 146, 147, 148, 149,\150, 151, 152, 153, 154, 155, 156, 157, 158, 159,\160, 161, 162, 163, 164, 165, 166, 167, 168, 169,\170, 171, 172, 173, 174, 175, 176, 177, 178, 179,\180, 181, 182, 183, 184, 185, 186, 187, 188, 189,\190, 191, 192, 193, 194, 195, 196, 197, 198, 199,\200, 201, 202, 203, 204, 205, 206, 207, 208, 209, }#define CONFIG_SYS_NAND_ECCSIZE         512
#define CONFIG_SYS_NAND_ECCBYTES        26
#define CONFIG_SYS_NAND_ONFI_DETECTION
#define CONFIG_NAND_OMAP_ECCSCHEME      OMAP_ECC_BCH16_CODE_HW#else
/*MX60LF8G18AC配置*/
#define CONFIG_SYS_NAND_PAGE_SIZE	2048
#define CONFIG_SYS_NAND_OOBSIZE		64
#define CONFIG_SYS_NAND_BLOCK_SIZE	(128*1024)/* NAND: driver related configs */
#define CONFIG_SYS_NAND_BAD_BLOCK_POS	NAND_LARGE_BADBLOCK_POS
#define CONFIG_SYS_NAND_ECCPOS		{ 2, 3, 4, 5, 6, 7, 8, 9, \10, 11, 12, 13, 14, 15, 16, 17, \18, 19, 20, 21, 22, 23, 24, 25, \26, 27, 28, 29, 30, 31, 32, 33, \34, 35, 36, 37, 38, 39, 40, 41, \42, 43, 44, 45, 46, 47, 48, 49, \50, 51, 52, 53, 54, 55, 56, 57, }#define CONFIG_SYS_NAND_ECCSIZE		512
#define CONFIG_SYS_NAND_ECCBYTES	14
#define CONFIG_SYS_NAND_ONFI_DETECTION
#define CONFIG_NAND_OMAP_ECCSCHEME      OMAP_ECC_BCH8_CODE_HW
#endif
#define CONFIG_SYS_NAND_U_BOOT_OFFS	0x00200000
/* NAND: SPL related configs */
#ifdef CONFIG_SPL_OS_BOOT
#define CONFIG_SYS_NAND_SPL_KERNEL_OFFS	0x00600000 /* kernel offset */
#endif
#endif /* !CONFIG_NAND */

做完上面修改后可以重新烧写,我的两块板子都可以正常启动。
4.下面以MT29F8G08ABABAWP为例,介绍一下如何通过芯片手册获取到上面头文件中宏的值及意义。
先看一下MT29F8G08ABABAWP的存储结构:

存储结构
可以看到单颗芯片的总容量是8640Mb=1080MB(为啥是1080MB呢?后面再说),里面有包含了两个plane(plane0,plane1),每个plane中又包含1024个blocks,每个block中又包含128个page。按照NAND读、写、擦出的操作要求,擦操作最小单位为一个block,读写操作最小单位为一个page,且写操作之前必须要先进行擦除操作。因此一个最小的操作单位是一个block(这里就解释了上面为啥NAND.SPL分区是128K时在MT29F8G08ABABAWP会提示对齐错误的原因了),整个block中产生任何一处不可修复的位错误,我们就认为这个块是坏块。

Page:MT29F8G08ABABAWP中一个page的大小为4K+224B,其中4K是数据区,224B是OOB区。其中oob区域的前两个字节用户坏块管理。

Block:MT29F8G08ABABAWP中一个block的大小为512K+28K,其中512K是所有页数据区的总和,28K是所有oob区的总和。

因为MT29F8G08ABABAWP每一个页都包含224B的OOB区域,所以最终所有的oob去加起来就是为啥1GB的nand最后算出来的总空间却是1080MB的原因。

宏参数的确定:

#define CONFIG_SYS_NAND_PAGE_SIZE       4096 //page中不包含OOB区域的大小 4K
#define CONFIG_SYS_NAND_OOBSIZE         224 //page中OOB区域的大小 224Bytes
#define CONFIG_SYS_NAND_BLOCK_SIZE      (512*1024) //block的大小,不包含OOB区域, 512K
#define CONFIG_SYS_NAND_BAD_BLOCK_POS   NAND_LARGE_BADBLOCK_POS //OOB区中标识是否坏块的位置,一般位于前两个字节。
/*下面CONFIG_SYS_NAND_ECCPOS定义的是一个数组,记录OOB区中用于存放ECC校验结果的位置,
因前两个字节被用于坏块标识,所以这里从2开始,只有为啥没到224(oob size)后面还留了几个字节,我也不清楚,晓得的伙伴评论区留言。*/
#define CONFIG_SYS_NAND_ECCPOS  { 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,\16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, \28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39,\40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51,\52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,\64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75,\76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87,\88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99,\100, 101, 102, 103, 104, 105, 106, 107, 108, 109,\110, 111, 112, 113, 114, 115, 116, 117, 118, 119,\120, 121, 122, 123, 124, 125, 126, 127, 128, 129,\130, 131, 132, 133, 134, 135, 136, 137, 138, 139,\140, 141, 142, 143, 144, 145, 146, 147, 148, 149,\150, 151, 152, 153, 154, 155, 156, 157, 158, 159,\160, 161, 162, 163, 164, 165, 166, 167, 168, 169,\170, 171, 172, 173, 174, 175, 176, 177, 178, 179,\180, 181, 182, 183, 184, 185, 186, 187, 188, 189,\190, 191, 192, 193, 194, 195, 196, 197, 198, 199,\200, 201, 202, 203, 204, 205, 206, 207, 208, 209, }
#define CONFIG_NAND_OMAP_ECCSCHEME      OMAP_ECC_BCH16_CODE_HW //校验方式#define CONFIG_SYS_NAND_ECCSIZE         512  //标识多长字节进行一次ECC校验#define CONFIG_SYS_NAND_ECCBYTES        26 //是每次计算ECC产生校验码的字节数,取值参考下表:

在这里插入图片描述
这里说一下CONFIG_NAND_OMAP_ECCSCHEME宏,这个宏是根据什么选择是那种校验方式的呢?在am35x的手册中关于sysboot[9]的作用做了以下描述“for ANND and NANDI2C boot:NAND ECC For fast external boot:must be 0b”,“0=ECC done by ROM 1=handled by NAND”,可以看出当sysboot[9]设置下拉时(我的硬件就是下拉)当ROM中的固件读取NAND中MLO阶段程序时,会采用ROM固件中定义的校验方式来进行校验。而MT29F8G08ABABAWP采用的是BCH16,MX60LF8G18AC采用的是BCH8。另外在uboot中读NAND的数据,如果选择的校验方式和之前写入是的校验方式不同,就会提示ECC的错误。
另外测试验证过程中在给NAND.SPL写入MLO文件的时候,提示“Size of write exceeds partition or device limit 0 bytes written: ERROR”,这个情况是因为NAND.SPL大小刚好分配的是一个block的大小,当这个block内有地址不能读写时会被标记为坏块,从而导致NAND.SPL分区不能被读写,导致上面写错误。这一点也刚好验证nand是以block为最小操作单元的事实,对于nand坏块的查看可以通过nand bad或者nand erase.chip查看,注意第二个命令会擦除芯片。另外NAND读写时在遇到坏块会自动避开,所以如果NAND.SPL坏块就会自动跳到下一个分区NAND.SPL.backup1中读取,鉴于这一点可以多定义几个备份区,当有坏块是可以从下一个备份区启动。
在这里插入图片描述

注意:这里修改了分区校验方式,在内核移植过程中也需要在dts中修改分区和校验方式。

5.最后就是配置头文件中的环境变量信息,使其启动后能自动拉起内核不运行。这里在不做分析,具体的照着官方给的copy过来就行。到此uboot中NAND的移植过程完成。

下面是一些移植过程中参考的文档,还有部分文档未一一列出,再次对这些无私的贡献者表示感谢。
参考文档:
https://blog.csdn.net/ccwzhu/article/details/109605076
https://blog.csdn.net/qq_41882586/article/details/123232813

这篇关于AM335x uboot中Nand Flash调试的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/493311

相关文章

C++中实现调试日志输出

《C++中实现调试日志输出》在C++编程中,调试日志对于定位问题和优化代码至关重要,本文将介绍几种常用的调试日志输出方法,并教你如何在日志中添加时间戳,希望对大家有所帮助... 目录1. 使用 #ifdef _DEBUG 宏2. 加入时间戳:精确到毫秒3.Windows 和 MFC 中的调试日志方法MFC

ASIO网络调试助手之一:简介

多年前,写过几篇《Boost.Asio C++网络编程》的学习文章,一直没机会实践。最近项目中用到了Asio,于是抽空写了个网络调试助手。 开发环境: Win10 Qt5.12.6 + Asio(standalone) + spdlog 支持协议: UDP + TCP Client + TCP Server 独立的Asio(http://www.think-async.com)只包含了头文件,不依

如何在Visual Studio中调试.NET源码

今天偶然在看别人代码时,发现在他的代码里使用了Any判断List<T>是否为空。 我一般的做法是先判断是否为null,再判断Count。 看了一下Count的源码如下: 1 [__DynamicallyInvokable]2 public int Count3 {4 [__DynamicallyInvokable]5 get

计算机毕业设计 大学志愿填报系统 Java+SpringBoot+Vue 前后端分离 文档报告 代码讲解 安装调试

🍊作者:计算机编程-吉哥 🍊简介:专业从事JavaWeb程序开发,微信小程序开发,定制化项目、 源码、代码讲解、文档撰写、ppt制作。做自己喜欢的事,生活就是快乐的。 🍊心愿:点赞 👍 收藏 ⭐评论 📝 🍅 文末获取源码联系 👇🏻 精彩专栏推荐订阅 👇🏻 不然下次找不到哟~Java毕业设计项目~热门选题推荐《1000套》 目录 1.技术选型 2.开发工具 3.功能

什么是 Flash Attention

Flash Attention 是 由 Tri Dao 和 Dan Fu 等人在2022年的论文 FlashAttention: Fast and Memory-Efficient Exact Attention with IO-Awareness 中 提出的, 论文可以从 https://arxiv.org/abs/2205.14135 页面下载,点击 View PDF 就可以下载。 下面我

vscode中文乱码问题,注释,终端,调试乱码一劳永逸版

忘记咋回事突然出现了乱码问题,很多方法都试了,注释乱码解决了,终端又乱码,调试窗口也乱码,最后经过本人不懈努力,终于全部解决了,现在分享给大家我的方法。 乱码的原因是各个地方用的编码格式不统一,所以把他们设成统一的utf8. 1.电脑的编码格式 开始-设置-时间和语言-语言和区域 管理语言设置-更改系统区域设置-勾选Bata版:使用utf8-确定-然后按指示重启 2.vscode

STM32内部闪存FLASH(内部ROM)、IAP

1 FLASH简介  1 利用程序存储器的剩余空间来保存掉电不丢失的用户数据 2 通过在程序中编程(IAP)实现程序的自我更新 (OTA) 3在线编程(ICP把整个程序都更新掉) 1 系统的Bootloader写死了,只能用串口下载到指定的位置,启动方式也不方便需要配置BOOT引脚触发启动  4 IAP(自己写的Bootloader,实现程序升级) 1 比如蓝牙转串口,

STM32 ADC+DMA导致写FLASH失败

最近用STM32G070系列的ADC+DMA采样时,遇到了一些小坑记录一下; 一、ADC+DMA采样时进入死循环; 解决方法:ADC-dma死循环问题_stm32 adc dma死机-CSDN博客 将ADC的DMA中断调整为最高,且增大ADCHAL_ADC_Start_DMA(&hadc1, (uint32_t*)adc_buffer, ADC_Buffer_Size); 的ADC_Bu

起点中文网防止网页调试的代码展示

起点中文网对爬虫非常敏感。如图,想在页面启用调试后会显示“已在调试程序中暂停”。 选择停用断点并继续运行后会造成cpu占用率升高电脑卡顿。 经简单分析网站使用了js代码用于防止调试并在强制继续运行后造成电脑卡顿,代码如下: function A(A, B) {if (null != B && "undefined" != typeof Symbol && B[Symbol.hasInstan