【自制DA14531手环(仿小米手环4/5)开发套件】配套教程 之 一:开发环境 + 入门..
<div class='showpostmsg'> 本帖最后由 辛昕 于 2024-1-23 13:14 编辑<p><strong><span style="color:#e74c3c;"><span style="font-size:20px;">本系列配套教程其他连接如下:</span></span></strong></p>
<p><span style="color:#000000;"><span style="font-size:20px;">配套教程 之 三:项目git说明和我的BSP</span></span><strong><span style="color:#e74c3c;"><span style="font-size:20px;"> <a href="https://bbs.eeworld.com.cn/thread-1270515-1-1.html" target="_blank">https://bbs.eeworld.com.cn/thread-1270515-1-1.html</a></span></span></strong></p>
<p> </p>
<p><strong><span style="font-size:24px;"><span style="color:#000000;">贴上后面的楼层的内容目录:</span></span></strong></p>
<p><span style="font-size:18px;"><strong>1-0、首贴介绍缘由(即本楼)</strong></span></p>
<p><span style="font-size:18px;"><span style="color:#27ae60;"><strong>1-1、开发环境所需;</strong></span></span></p>
<p><span style="font-size:18px;"><span style="color:#27ae60;"><strong>1-2、SDK(_6.0.20.1338) 和 (非蓝牙)简单外设例程 的 Keil5 MDK 配置简单说明</strong></span></span></p>
<p><span style="font-size:18px;"><span style="color:#27ae60;"><strong>1-3、DA14531的程序是在RAM里跑的</strong></span></span></p>
<p><span style="font-size:18px;"><span style="color:#27ae60;"><strong>1-4、程序在RAM里跑?所以,DA14531到底有多大FLASH,有多大RAM?</strong></span></span></p>
<p><span style="font-size:18px;"><span style="color:#27ae60;"><strong>1-5、SmartBond Flash Programmer 和 烧录地址大小问题</strong></span></span></p>
<p><span style="font-size:18px;"><span style="color:#27ae60;"><strong>1-6、JLink的RTT如何使用(替代、节省调试串口)</strong></span></span></p>
<p><span style="color:#27ae60;"><span style="font-size:18px;"><strong>1-7、Telnet的方式,XShell连接JLink RTT,实现更强大的日志功能</strong></span></span></p>
<p><span style="color:#27ae60;"><span style="font-size:18px;"><strong>1-8、日常操作——Keil5 MDK Debug我们在View什么?</strong></span></span></p>
<p><span style="color:#27ae60;"><span style="font-size:18px;"><strong>1-9、脱离了调试开发的怀抱——用JLink Commander实现调试;</strong></span></span></p>
<p><span style="color:#27ae60;"><span style="font-size:18px;"><strong>1-10、JLink推出的Ozone——图形化JLink调试工具;</strong></span></span></p>
<p> </p>
<p><span style="color:#95a5a6;"><span style="font-size:18px;"><strong>1-11、简单介绍 non-ble的 peripheral_project 的例程结构的简单介绍。</strong></span></span></p>
<p><span style="color:#95a5a6;"><span style="font-size:18px;"><strong>关于这个,我昨天写吐了,就没继续写,后来我想了想,回头再开个帖子单独说说</strong></span></span></p>
<p><span style="color:#95a5a6;"><span style="font-size:18px;"><strong>虽然这是个很简单的问题,但我突然很想说说我多年来已经形成的 BSP到底的习惯</strong></span></span></p>
<p> </p>
<p> </p>
<p><span style="font-family:楷体;"><strong><span style="color:#3498db;"><span style="font-size:24px;">下面是首贴正文: 缘由</span></span></strong></span></p>
<p><span style="color:#000000;"><span style="font-size:16px;">熟悉(拆解)小米手环的朋友,应该对Dialog Semiconductor旗下的系列蓝牙SoC DA145XX DA146XX 很熟悉。</span></span></p>
<p><span style="color:#000000;"><span style="font-size:16px;">本人几年前做过可穿戴开发,也对这个形态的产品很感兴趣。</span></span></p>
<p><span style="color:#000000;"><span style="font-size:16px;">不过,我对现在手环的通用功能并不十分感冒。</span></span></p>
<p> </p>
<p><span style="color:#000000;"><span style="font-size:16px;">于是很早就萌生了要自己DIY的念头。</span></span></p>
<p><span style="color:#000000;"><span style="font-size:16px;">然而,DIY一个成品远不是画个板子,贴片撸代码这么简单。</span></span></p>
<p><span style="color:#000000;"><span style="font-size:16px;">光一个外壳就让我这个写代码为主,不会结构的人左右为难.......</span></span><span style="color:#000000;"><span style="font-size:16px;"></span></span></p>
<p><span style="color:#000000;"><span style="font-size:16px;">——这个套件目前第一步是先推出一个在外形上兼容 小米手环4/5的 PCBA,后续我将为外壳而努力,或者希望,有</span></span></p>
<p><span style="color:#000000;"><span style="font-size:16px;">了解、熟悉这一块的朋友加入,帮忙</span></span></p>
<p><span style="color:#000000;"><span style="font-size:16px;">——因为,我没钱给你。</span></span></p>
<p> </p>
<p><span style="color:#000000;"><span style="font-size:16px;">与其说我对手环很感兴趣,不如说我对手环这个形态的产品很感兴趣。</span></span></p>
<p><span style="color:#000000;"><span style="font-size:16px;">无他——因为它戴在人手上,比手机轻,比手机小——确切说,用户使用它,相对手机更加无感。</span></span></p>
<p><span style="color:#000000;"><span style="font-size:16px;">这,也是可穿戴类产品最有价值的地方——我个人以为。</span></span></p>
<p> </p>
<p><span style="color:#000000;"><span style="font-size:16px;">但是,我对于市面上通用的手环功能非常不感冒。</span></span></p>
<p><span style="color:#000000;"><span style="font-size:16px;">比如说,计步——所以,在我的这一版里,一个出于我不感冒,另一个</span></span></p>
<p><span style="color:#000000;"><span style="font-size:16px;">也是出于我选用了最小的DA14531芯片,目前,所有IO口已经被我用尽,所以,尽管我本想预留一个GSENSOR芯片</span></span></p>
<p><span style="color:#000000;"><span style="font-size:16px;">却也暂时不得。</span></span></p>
<p><span style="color:#000000;"><span style="font-size:16px;">(后续,如有需要,我会考虑换一颗同系列MCU)。</span></span></p>
<p> </p>
<p><span style="color:#000000;"><span style="font-size:16px;">更大的希望,其实是,我希望把这个东西做成一个开放套件。</span></span></p>
<p><span style="color:#000000;"><span style="font-size:16px;">让所有其他和我一样,希望实现某个手环形态产品DIY的人,可以有一个现成的平台可用。</span></span></p>
<p> </p>
<p><span style="color:#000000;"><span style="font-size:16px;">因为,类似的东西,过去,我从来没见到——</span></span></p>
<p><span style="color:#000000;"><span style="font-size:16px;">曾几何时,所谓的百度手环,它其实没有流出硬件部分,我记得好像是这样,且不说那个软件写得如何,也就是纯粹一个开源软件而已。</span></span></p>
<p><span style="color:#000000;"><span style="font-size:16px;">当然,后来有一段时间,我也看到一些基于DA14580的所谓开源手环项目——</span></span></p>
<p><span style="color:#000000;"><span style="font-size:16px;">这些东西却配了一个.......怎么说呢?那个东西,我相信你不会想戴在手上的。</span></span></p>
<p> </p>
<p><span style="color:#000000;"><span style="font-size:16px;">所以,我做的这个东西,我选择了在外形上向小米手环靠近,不去考虑里面可能涉及的一些版权风险。</span></span></p>
<p><span style="color:#000000;"><span style="font-size:16px;">我的目的是希望能尽可能在外形上复刻小米手环,并一定程度上利用它的周边生态——</span></span></p>
<p><span style="color:#000000;"><span style="font-size:16px;">例如,已经形成小有规模的各式手环表带。</span></span></p>
<p> </p>
<p><span style="color:#000000;"><span style="font-size:16px;">另一方面,也是出于,我个人认为小米手环,无论性价比,还是外形,它一代代演进,至今已到小米8.</span></span></p>
<p> </p>
<p><span style="color:#000000;"><span style="font-size:16px;">我个人,除了第二代,以及最新的8,几乎每一款我都拥有过。</span></span></p>
<p><span style="color:#000000;"><span style="font-size:16px;">我对它的外观进步是非常欣赏的。</span></span></p>
<p><span style="color:#000000;"><span style="font-size:16px;">尽管个人DIY,我毫无信心可以复制它的美观。</span></span></p>
<p> </p>
<p><span style="color:#000000;"><span style="font-size:16px;"></span></span></p>
<p><strong><span style="font-size:16px;">但是,立一个光辉的榜样总是没坏的。</span></strong></p>
<p><span style="color:#000000;"><span style="font-size:16px;">当然,这些都是后话。</span></span></p>
<p><span style="color:#000000;"><span style="font-size:16px;">目前,第一步,仍然是一个PCBA,目前,这个板子已经交由坛友 @Rex 在画。</span></span></p>
<p><span style="color:#000000;"><span style="font-size:16px;">相信很快可以到立创上 打板贴料。</span></span></p>
<p> </p>
<p><span style="color:#000000;"><span style="font-size:16px;">这个帖子,我将集中做一些我认为必要的,类似开发板教程一样的东西。</span></span></p>
<p> </p>
<p><span style="color:#000000;"><span style="font-size:16px;">因为,DA14XXX系列的MCU,教程其实很少,更不要说像STM32一样如此丰富的生态。</span></span></p>
<p> </p>
<p><span style="color:#000000;"><span style="font-size:16px;">真的——你们到淘宝上,除了去买从海外运进来的官方开发板——很贵。</span></span></p>
<p><span style="color:#000000;"><span style="font-size:16px;">USB那块,就是我现在手上的这块,也要将近300块钱。</span></span></p>
<p><span style="color:#000000;"><span style="font-size:16px;">那块pro,更贵,要一千多块钱。</span></span></p>
<p> </p>
<p><span style="color:#000000;"><span style="font-size:16px;">除此以外,最小系统板、开发板,我一块都没见到。</span></span></p>
<p><span style="color:#000000;"><span style="font-size:16px;">事实上,不要说DA14531,除了最早的DA14580和DA14585,淘宝上能看到相对便宜的开发板(也就是一百多块的常规价)</span></span></p>
<p><span style="color:#000000;"><span style="font-size:16px;">以外,其他更新的型号,基本上,很难找到资源,只能自己打板。</span></span></p>
<p> </p>
<p><span style="color:#000000;"><span style="font-size:16px;">至于教程,倒不是没有,但也是千抄白抄,来来去去就那么几份。</span></span></p>
<p><span style="color:#000000;"><span style="font-size:16px;">而我跟人在这个熟悉和使用DA14531的过程中,尽管也翻遍这些教程。</span></span></p>
<p><span style="color:#000000;"><span style="font-size:16px;">却觉得它们说的很肤浅,对很多至关重要的问题,都基本没有提及。</span></span></p>
<p> </p>
<p><span style="color:#000000;"><span style="font-size:16px;">因此,在等待这块我们自己的这块从一开始就面向手环成品的开发套件硬件新鲜出炉的同时</span></span></p>
<p><span style="color:#000000;"><span style="font-size:16px;">我将逐渐将我这段时间,自己在这块板子上的熟悉、学习、了解过程,发表在这个帖子下。</span></span></p>
<p><span style="color:#000000;"><span style="font-size:16px;">权当资料。</span></span></p>
<p> </p>
<p><span style="color:#000000;"><span style="font-size:16px;">同时,Dialog官方是没有在 DA14531上移植FreeRTOS的,使用的是Rivera Waves这个伪系统。</span></span></p>
<p><span style="color:#000000;"><span style="font-size:16px;">然而我个人的经验是,这类不带真正独立线程和可抢占特性的系统,写起程序,其实挺麻烦的。</span></span></p>
<p><span style="color:#000000;"><span style="font-size:16px;">所以,我自己移植了。</span></span></p>
<p><span style="color:#000000;"><span style="font-size:16px;">目前,已经初步完成,并已完成基本的 创建任务 跑起来的测试。</span></span></p>
<p><span style="color:#000000;"><span style="font-size:16px;">后续的其他测试将陆续完成、补充。</span></span></p>
<p> </p>
</div><script> var loginstr = '<div class="locked">查看精华帖全部内容,请<a href="javascript:;" style="color:#e60000" class="loginf">登录</a>或者<a href="https://bbs.eeworld.com.cn/member.php?mod=register_eeworld.php&action=wechat" style="color:#e60000" target="_blank">注册</a></div>';
if(parseInt(discuz_uid)==0){
(function($){
var postHeight = getTextHeight(400);
$(".showpostmsg").html($(".showpostmsg").html());
$(".showpostmsg").after(loginstr);
$(".showpostmsg").css({height:postHeight,overflow:"hidden"});
})(jQuery);
}
</script><script type="text/javascript">(function(d,c){var a=d.createElement("script"),m=d.getElementsByTagName("script"),eewurl="//counter.eeworld.com.cn/pv/count/";a.src=eewurl+c;m.parentNode.insertBefore(a,m)})(document,523)</script> 本帖最后由 辛昕 于 2024-1-18 01:57 编辑
<p><span style="color:#000000;"><span style="font-size:24px;">1-1.开发环境所需</span></span></p>
<p> </p>
<p><span style="font-size:16px;"><span style="color:#000000;">DA14531的开发环境是我们熟悉的 Keil JLink那一套东西,非常好。</span></span></p>
<p><span style="font-size:16px;"><span style="color:#000000;">简单说一下,需要什么东西,以便准备好,节省时间</span></span></p>
<p><span style="color:#000000;"><span style="font-size:16px;"><strong> a.Keil5 MDK </strong></span></span></p>
<p><span style="color:#000000;"><span style="font-size:16px;"><strong> b.DA1453x pack</strong></span></span></p>
<p><span style="color:#000000;"><span style="font-size:16px;"><strong> c.SDK(SDK_6.0.20.1338)</strong></span></span></p>
<p><span style="color:#000000;"><span style="font-size:16px;"><strong> d.JLink (v7.92h)</strong></span></span></p>
<p><span style="color:#000000;"><span style="font-size:16px;"><strong> e.SmartBond Flash Programmer</strong></span></span></p>
<p> </p>
<p><span style="color:#000000;"><span style="font-size:16px;"> 1、安装Keil5 MDK 和 DA1453x 系列的 pack</span></span></p>
<p><span style="color:#000000;"><span style="font-size:16px;"> 这一点不必多说,只是要说明两点:</span></span></p>
<p> </p>
<p><span style="color:#000000;"><span style="font-size:16px;"> DA14531是一个相对比较新的器件,因此如果你和我一样,已经很久更新Keil5的版本的话,那大概率是无法支持的,因此要升级到较新的版本。</span></span></p>
<p><span style="color:#000000;"><span style="font-size:16px;">目前我实测,可以确认的是,5.36是肯定可以的,而我用的也是这个版本;</span></span></p>
<p><span style="color:#000000;"> </span></p>
<p> </p>
<p><span style="color:#000000;"> <span style="font-size:16px;">至于DA14531的pack文件,要依赖keil5自己更新,不知道是否和科学上网有关,反正基本都是失败的,所以一般我都是用离线方式完成;这里也不多会说,只附上最新的 DA14531.DFP文件;</span></span></p>
<p> </p>
<p><span style="color:#000000;"><span style="font-size:16px;"> 第二点要注意的是,Keil5从5.2x版本开始,就<strong>不再使用老的AC5编译器了,而采用AC6</strong>,这玩意变化很大,当然具体是什么我没太多研究。</span></span></p>
<p><span style="color:#000000;"><span style="font-size:16px;">但它对开发引起的变化却不小,比如说,由目前STM32CubeMX生成的STM32工程,它仍然只适用以往的AC5编译器,所以使得我们在做的时候,仍然需要另外安装AC5编译器,并且在Keil5里设置使用;(<a href="https://bbs.eeworld.com.cn/thread-1254925-1-1.html" target="_blank">这个和DA14531没关系,我以前在STM32G030的相关帖子里提过,有需要可以去哪里看到</a>)。</span></span></p>
<p><span style="color:#000000;"><span style="font-size:16px;"> 当然,最新的DA14531的SDK6所使用的正正是AC6编译器,所以无需操心,然而,后面,因为我自己把FreeRTOS移植过来,则会涉及一些变化,这些将在后续下一讲,专门提到FreeRTOS的移植的时候再细说;</span></span></p>
<p> </p>
<div></div>
本帖最后由 辛昕 于 2024-1-18 01:47 编辑
<p><span style="color:#000000;"><strong><span style="font-size:24px;">1-2.SDK(<span lang="EN-US"><span style="font-family:等线">_6.0.20.1338</span></span><span style="font-family:等线">) 和 (非蓝牙)简单外设例程 的 Keil5 MDK 配置简单说明</span></span></strong></span></p>
<p><span style="color:#000000;"><span style="font-size:16px;">目前,针对DA145XX系列的最新SDK版本,是SDK6,最新子版本,正是上述这个版本。</span></span></p>
<p><span style="color:#000000;"><span style="font-size:16px;">可以自行到瑞萨官网下载(Dialog Semiconductor被瑞萨收购了,现在是瑞萨的芯片了)</span></span></p>
<p> </p>
<p><span style="color:#000000;"><span style="font-size:16px;">当然,后续我会用git的方式,把我所开发使用的代码,上传到gitee,你们可以自行从哪里下载和同步到我最新的代码</span></span></p>
<p> </p>
<p><span style="color:#000000;"><span style="font-size:16px;">瑞萨官网有一份关于SDK的Get Started简要说明,不过是网页,所以没有下载下来。</span></span></p>
<p><span style="font-size:16px;"><span style="color:#000000;">可点击依次查看:</span><a href="https://lpccs-docs.renesas.com/Tutorial_SDK6/index.html" style="color:#0563c1; text-decoration:underline">https://lpccs-docs.renesas.com/Tutorial_SDK6/index.html</a></span></p>
<p> </p>
<p><span style="color:#000000;"><span style="font-size:16px;">以下这幅图就出自其中的 SDK Architecture(SDK结构)章节</span></span></p>
<p> </p>
<p><span style="color:#000000;"><span style="font-size:16px;">目前,出于简单考虑——从最基础的例程入手,有助于更容易了解DA14531项目文件的设置和一些共性的东西。</span></span></p>
<p><span style="color:#000000;"><span style="font-size:16px;">何况,我初步要实现的一个程序,也不包含蓝牙。</span></span></p>
<p><span style="color:#000000;"><span style="font-size:16px;">所以我们从其中的 peripheral_examples入手,即最基础的单一外设例程。</span></span></p>
<p> </p>
<p><span style="color:#000000;"><span style="font-size:16px;">1.从 例程blinky开始</span></span></p>
<p><span style="color:#000000;"><span style="font-size:16px;">这基本是所有例程里最简单的一个,只是简单的LED闪烁,最多再加个串口打印;</span></span></p>
<p><span style="color:#000000;"><span style="font-size:16px;">首先,要从图中红线处,这个东西叫 “工程选项”,选择 DA14531</span></span></p>
<p> </p>
<p> </p>
<p><span style="color:#000000;"><span style="font-size:16px;">对于例程来说,它可以不做任何设置,直接编译下载即可。</span></span></p>
<p><span style="color:#000000;"><span style="font-size:16px;">但我们还是要特别提几个对于后面要介绍比较重要的地方。</span></span></p>
<p> </p>
<p><span style="color:#000000;"><span style="font-size:16px;">首先就是芯片型号</span></span></p>
<p> </p>
<p><span style="color:#000000;"><span style="font-size:16px;">例程里,它默认选的是 ARMCM0P——也就是 Cortex M0+</span></span></p>
<p><span style="color:#000000;"><span style="font-size:16px;">事实证明,选择这个选项,也一点关系都没有,照样可以成功跑起来。</span></span></p>
<p><span style="color:#000000;"><span style="font-size:16px;">然而,这个选项之下,其实对于ROM和RAM的配置是有点问题的——</span></span></p>
<p> </p>
<p><span style="color:#000000;"><span style="font-size:16px;">因为很明显,DA14531的RAM并没有这么大,而且它也不是从0x20000000开始。</span></span></p>
<p><span style="color:#000000;"><span style="font-size:16px;">如果你按照前面说明,成功安装 DA14531的DFP文件。</span></span></p>
<p><span style="color:#000000;"><span style="font-size:16px;">那么,你可以在Device里看到DA14531,然后我们来看看它的ROM和RAM设置</span></span></p>
<p> </p>
<p> </p>
<p> </p>
<p><span style="color:#000000;"><span style="font-size:16px;">这才是符合DA14531芯片的ROM RAM大小和起始地址。</span></span></p>
<p><span style="color:#000000;"><span style="font-size:16px;">DA14531的RAM只有48K,而且,它不同于STM32等我们以前用过的32位单片机,它的起始地址并非0x20000000</span></span></p>
<p><span style="color:#000000;"><span style="font-size:16px;">同样的,DA14531的ROM和我们以前熟悉的STM32的那个用来存放我们的应用程序的ROM也不一样,并且也不是从0x08000000开始。</span></span></p>
<p><span style="color:#000000;"><span style="font-size:16px;">关于DA14531的ROM和RAM,以及最重要的那个问题——程序到底在哪这种最关键的问题,我们后面再统一说。</span></span></p>
<p><span style="color:#000000;"><span style="font-size:16px;">现在只是提一下这个地方。</span></span></p>
<p> </p>
<p><span style="color:#e74c3c;"><span style="font-size:16px;">然而,这个地方,其实我到现在都没特别搞明白的地方——</span></span></p>
<ol>
<li><span style="color:#e74c3c;"><span style="font-size:16px;">ROM且放到一边不说,就说这个RAM,大小不同也就罢了,连起始地址都不对,为什么我们用ARMCM0P的设置也可以照样正常编译、调试、运行;</span></span></li>
<li><span style="color:#e74c3c;"><span style="font-size:16px;">还有一个类似的问题,后面FreeRTOS的移植和测试的时候,我发现一个同样比较难理解的问题:</span></span></li>
</ol>
<p><span style="color:#e74c3c;"><span style="font-size:16px;">默认来说,DA14531的堆大小只有区区256Byte(0x0000 0100),然而,对于FreeRTOS的默认情况来说,它涉及动态分配,创建的任务也是动态任务,此时,经过验证你会发现,FreeRTOSConfig.h中的最小可用堆大小,必须设置在1.5K多一些,才能正常运行一个最简单的任务。</span></span></p>
<p><span style="color:#e74c3c;"><span style="font-size:16px;">然而,1.5K明显比DA14531启动文件中的heap size要大得多。</span></span></p>
<p><span style="color:#e74c3c;"><span style="font-size:16px;">却为什么仍然可以正常跑,而不需要修改heap size?</span></span></p>
<p> </p>
<p><span style="color:#000000;"><span style="font-size:16px;">这两个问题目前来说我都没答案,估计前者涉及要查看后面提到的 .sct文件,后者则可能涉及FreeRTOS自己的实现代码;</span></span></p>
<p> </p>
<p> </p>
<p><span style="color:#2980b9;"><span style="font-size:16px;">另外,关于这两个sct,目前我简单替换试了试,对例程的编译、调试、没有区别,目前还不知道有什么区别。</span></span></p>
<p><span style="color:#2980b9;"><span style="font-size:16px;">Clang我只知道它是一个编译器,但我其实不是很了解它和原来的C/C++编译器有什么区别?</span></span></p>
<p><span style="color:#000000;"><span style="font-size:16px;">关于Keil5 MDK里的项目配置就简说到这里。</span></span></p>
<p><span style="color:#000000;"><span style="font-size:16px;">剩下的事情,就比较简单。</span></span></p>
<p><span style="color:#000000;"><span style="font-size:16px;">就像平常一样,点击Debug即可开始调试;</span></span></p>
<p> </p>
<p><strong><span style="color:#000000;"><span style="font-size:24px;">USB-DEV P01 和 P06 丝印印错</span></span></strong></p>
<p><span style="color:#000000;"><span style="font-size:16px;">最后要说的一点是——如果,你和我一样,一开始是使用官方的USB-Dev开发板——因为目前为止,淘宝上还没有人做过一个DA14531的开发板。</span></span></p>
<p><span style="color:#000000;"><span style="font-size:16px;">那么,在用到串口输出的时候,你要注意,这块USB-DEV的丝印,P01和P06是互掉了的——</span></span></p>
<p><span style="color:#000000;"><span style="font-size:16px;">我是在发现串口没输出,回头检查原理图的时候才发现的。</span></span></p>
<p> </p>
<p><span style="color:#000000;"><span style="font-size:16px;">当面,这两个图,是左右对称相反的。实际证明,要以原理图为准,如果按照丝印连接,会发现串口没有输出;</span></span></p>
<p> </p>
<p> </p>
<p><span style="color:#000000;"><span style="font-size:16px;">但接下来要说的问题,是一个和以往我们使用STM32/51比较大区别的地方。</span></span></p>
<p><span style="color:#000000;"><span style="font-size:16px;">那就是,如果你试过在调试过后,掉电重启,你会发现,程序没有按照刚刚调试的时候跑起来,这是怎么回事呢?</span></span></p>
<p> </p>
<p><span style="color:#000000;"><span style="font-size:16px;">这里简单提一个后面才会提到的结论:</span></span></p>
<p><span style="font-size:16px;"><span style="color:#2980b9;">按照这块USB-DEV的硬件配置方式——其实这种方式也是大多数时候采用DA14531做单一主控的时候,会采用的方式。</span></span></p>
<p><span style="font-size:16px;"><span style="color:#2980b9;">就是在片外接一块spi flash芯片。</span></span></p>
<p><span style="font-size:16px;"><span style="color:#2980b9;">然后通过DA14531自己提供的工具,把程序烧录到片外spi Flash上。</span></span></p>
<p> </p>
<p><span style="font-size:16px;"><span style="color:#2980b9;">或者说,一旦你的代码调试稳定,从此不再调整,也不考虑升级的情况下,那么,你还可以把程序烧录到片内的OTP——</span></span></p>
<p><span style="font-size:16px;"><span style="color:#2980b9;">OTP也是一种存储器类型,和FLASH不同的是,它只能烧录一次。</span></span></p>
<p><span style="font-size:16px;"><span style="color:#2980b9;">但它的成本比FLASH要低地多。</span></span></p>
<p><span style="font-size:16px;"><span style="color:#2980b9;">所以,对于那些稳定,不需要再修改的固件,使用OTP可以大幅度降低成本,因此在成熟量产产品中也被大量使用。</span></span></p>
<p><span style="font-size:16px;"><span style="color:#2980b9;">DA14531片内配置的OTP大小为32KB。</span></span></p>
<p><strong><span style="color:#000000;"><span style="line-height: 240%;"><span style="font-size: 22pt; font-family: 等线;">1-3.DA14531的程序是在RAM里跑的</span></span></span></strong></p>
<p> </p>
<p><span style="color:#000000;"><span style="font-size:16px;"><font face="等线">这个问题——其实我认为是这个帖子里,最重要的一部分,内容也比较多,希望耐心看。</font></span></span></p>
<p> </p>
<p><span style="color:#000000;"><span style="font-size:16px;">无论是51,还是STM32,我们已经很习惯了 ROM+RAM,或者说FLASH+RAM的结构配置。</span></span></p>
<p ><span style="color:#000000;"><span style="font-size:16px;">乍看之下,DA14531片上,同样有ROM,有RAM——而且还分成了3块RAM。</span></span></p>
<p > </p>
<p ><span style="color:#000000;"><span style="font-size:16px;">而且ROM看起来还挺大,144KB。</span></span></p>
<p ><span style="color:#000000;"><span style="font-size:16px;">然而,这块ROM和我们平常熟悉的那个ROM完全不是一回事——我的意思,你写的应用代码就不是放在这个位置,这144KB实际上是用来存放蓝牙协议栈和bootloader(<b>当然,datasheet不是这么叫的,但意思就是</b>)的。</span></span></p>
<p > </p>
<p ><span style="color:#000000;"><span style="font-size:16px;">我们可以从datasheet的Memory Map来确认——</span></span></p>
<p ><span style="color:#000000;"><span style="font-size:16px;">这里提一句:</span></span></p>
<p ><strong><span style="color:#e74c3c;"><span style="font-size:16px;">DA14531不像STM32,有一堆的资料和各种各样的教程。它也不分什么RM或者寄存器手册。</span></span></strong></p>
<p ><strong><span style="color:#e74c3c;"><span style="font-size:16px;">关于DA14531的所有内容,基本上,全在这份长达300多页的datasheet里。</span></span></strong></p>
<p ><strong><span style="color:#e74c3c;"><span style="font-size:16px;">所以,有什么想知道的,不要抱有什么幻想,基本上只能靠在这300多页的datasheet里寻找答案。</span></span></strong></p>
<p > </p>
<p > </p>
<p ><span style="font-size:16px;"><span style="color:#000000;">还记得前面,在Keil5里Option的Target标签页里看到的么?</span></span></p>
<p ><span style="font-size:16px;"><span style="color:#000000;">那里的ROM,地址就是在 0x07F00000到0x07F24000之间(0x24000算一算,没错,就是144KB)</span></span></p>
<p ><span style="font-size:16px;"><span style="color:#000000;">这个东西,就是上面的框图里那144KB的ROM。</span></span></p>
<p ><span style="font-size:16px;"><span style="color:#000000;">简单地说,这ROM不是给我们用的;</span></span></p>
<p > </p>
<p ><span style="font-size:16px;"><span style="color:#000000;">这个时候,你会很好奇,如果是这样,那我们写的代码是在存储在哪里运行的?</span></span></p>
<p > </p>
<p ><span style="font-size:16px;"><span style="color:#000000;">无论是百度才知道所谓在RAM里执行,还是因为你像我一样,以前做过其他蓝牙,你可能就突然会想起所谓</span></span><strong><span style="font-size:18px;"><span style="color:#e74c3c;">“在RAM里执行”</span></span></strong><span style="font-size:16px;"><span style="color:#000000;">这个事情。</span></span></p>
<p > </p>
<p ><span style="font-size:16px;"><span style="color:#000000;">这个时候,我们需要进一步了解的问题就是——</span></span></p>
<p ><span style="font-size:16px;"><span style="color:#000000;">如果是这样,那么平时,代码存储在哪里?上电之际,它又是怎么加载入RAM的?</span></span></p>
<p ><span style="font-size:16px;"><span style="color:#000000;">——这个问题是很重要的,因为,它涉及到两件非常重要的事情——</span></span></p>
<p ><span style="color:#e74c3c;"><strong><span style="font-size:18px;">1、DA14531,你可用的CODE和DATA到底有多大?</span></strong></span></p>
<p><span style="color:#e74c3c;"><strong><span style="font-size:18px;">2、万一出现死机,你要对比着map去定位最后死在那个函数的时候,你都知道你的代码到底在哪里运行。</span></strong></span></p>
<p > </p>
<p ><span style="font-size:16px;"><span style="color:#000000;">这个时候,我们需要去看的是,MCU上电后,代码是怎么被load入ram。</span></span></p>
<p ><span style="font-size:16px;"><span style="color:#000000;">同样在datasheet中——</span></span></p>
<p > </p>
<p ><span style="color:#000000;"><span style="font-size:16px;">这个东西被叫做 BootROM Sequence,如果你不知道,没做过,那么你——</span></span></p>
<p ><strong><span style="color:#e74c3c;"><span style="font-size:18px;">只能和我一样,撸一遍datasheet目录甚至是整个datasheet,然后一半靠猜一半靠啃原文,去确认,这个东西是不是你要知道的那个东西。</span></span></strong></p>
<p > </p>
<p > </p>
<p ><span style="color:#000000;"><span style="font-size:16px;">这个流程图看似复杂——实际上,它也确实挺复杂。</span></span></p>
<p ><span style="color:#000000;"><span style="font-size:16px;">然而,总的来说,你会发现,无论怎么走(右侧的流程图来看),它最终都会走到 “Download Code to SRAM”。</span></span></p>
<p ><span style="color:#000000;"><span style="font-size:16px;">也就是说,右边的这么多种方式,无论是从串口、SPI传入,还是从最右侧提供的六种带有优先次序的载入方式,无论怎么走,它最终一定会把代码下载到 SRAM里。</span></span></p>
<p > </p>
<p ><span style="color:#000000;"><span style="font-size:16px;">而左侧的OTP方式也是如此——</span></span></p>
<p ><span style="color:#000000;"><span style="font-size:16px;">它也是把代码下载到SRAM里。</span></span></p>
<p > </p>
<p ><span style="color:#000000;"><span style="font-size:16px;">所有这些,最终走向一步,把SysRAM的地址重新映射到0,然后,软复位。</span></span></p>
<p ><span style="color:#000000;"><span style="font-size:16px;">说实话——</span></span></p>
<p ><span style="color:#000000;"><span style="font-size:16px;">这里的一些细节我们无从得知是干嘛用的。</span></span></p>
<p ><span style="color:#000000;"><span style="font-size:16px;">但是——</span></span></p>
<p > </p>
<p ><span style="color:#000000;"><span style="font-size:16px;">对于我们想知道的问题,知道上述信息已经基本够用。</span></span></p>
<p ><span style="color:#000000;"><span style="font-size:16px;">后面,如果我们要做OTA的时候,再参考相应工程来研究就可以了。</span></span></p>
<p ><span style="color:#000000;"><span style="font-size:16px;">当然,这幅流程图前后的文字,也应该仔细地阅读一下。</span></span></p>
<p ><span style="color:#000000;"><span style="font-size:16px;">不过,结论是类似的——对于我们想知道的,并没有太多用处,而是一些眼下我们还不明白也不需要明白的细节。</span></span></p>
<p ><span style="color:#000000;"><span style="font-size:16px;">唯一有用的是这么一张表,也就是如何从硬件上设置启动顺序。</span></span></p>
<p > </p>
<p ><span style="color:#000000;"><span style="font-size:16px;">这个图很好理解。</span></span></p>
<p ><span style="color:#000000;"><span style="font-size:16px;">它对应的就是上述流程图中,最右侧的那六个带有优先级次序的载入方式。</span></span></p>
<p > </p>
<p ><span style="color:#000000;"><span style="font-size:16px;">在这里,我不知道你会不会和我一样,会有两个问题想问:</span></span></p>
<ol>
<li ><span style="color:#000000;"><span style="font-size:16px;">说从片外spi flash载入代码,我能理解,毕竟你可以事先把代码存到flash芯片么,那么,其他方式,串口也罢,i2c也罢,那又是什么鬼?</span></span></li>
<li ><span style="color:#000000;"><span style="font-size:16px;">中间的 先串口后SPI的那个SPI和最右侧的 SPIM(aster) SPIS(lave)有什么区别?</span></span></li>
</ol>
<p > </p>
<p ><span style="color:#000000;"><span style="font-size:16px;">对于第一个问题,其实是比较好回答的——</span></span></p>
<p ><span style="color:#000000;"><span style="font-size:16px;">答案就是,我们可以把DA14531作为一个协处理器,当然是片外的,比如说,作为一个蓝牙收发模块。</span></span></p>
<p ><span style="color:#000000;"><span style="font-size:16px;">此时,我们的另一个主控制器,可以通过串口、I2C等方式,把DA14531的代码发送给DA14531;</span></span></p>
<p > </p>
<p ><span style="color:#000000;"><span style="font-size:16px;">而对于第二个问题,比较复杂。</span></span></p>
<p ><span style="color:#000000;"><span style="font-size:16px;">在这部分的文字描述里,我目前还不是十分确认这个细节过程,但如前所说,这对于目前我们想知道的问题来说,暂时没这个需要。</span></span></p>
<p ><span style="color:#000000;"><span style="font-size:16px;">我们唯一知道的就是,DA14531的代码载入方式非常丰富、灵活。</span></span></p>
<p > </p>
<p ><span style="color:#000000;"><span style="font-size:16px;">最后,关于这个问题,我还想最后说一点——</span></span></p>
<p ><span style="color:#000000;"><span style="font-size:16px;">对于熟悉51/STM32的我们来说,这种最终实际把代码载入RAM——片内RAM,这里称之为SysRAM的方式,似乎有点奇特。</span></span></p>
<p ><span style="color:#000000;"><span style="font-size:16px;">关于这一点,我们放到下一楼里说。</span></span></p>
<p><strong><span style="color:#000000;"><span style="font-size:24px;">1-4、程序在RAM里跑?所以,DA14531到底有多大FLASH,有多大RAM?</span></span></strong></p>
<p> </p>
<p><span style="color:#000000;"><span style="font-size:16px;">如果你有过在Linux或者Windows上开发C/C++程序的经历,你可能会觉得,这个方式反而更熟悉。</span></span></p>
<p><span style="color:#000000;"><span style="font-size:16px;">只要,你把(Sys)RAM理解成内存。</span></span></p>
<p><span style="color:#000000;"><span style="font-size:16px;">没错,事实上,就是如此。</span></span></p>
<p><span style="color:#000000;"><span style="font-size:16px;">在Linux/Windows或者其他的大型OS上,我们就是这样做的。</span></span></p>
<p><span style="color:#000000;"><span style="font-size:16px;">平常代码存储在硬盘上,然而,CPU总线并不能直接访问硬盘,它想快速地运行程序,就需要首先把程序载入内存条,让CPU可以直接执行取指、译码、运行等动作。</span></span></p>
<p> </p>
<p><span style="color:#000000;"><span style="font-size:16px;">关于这个问题,我们最后需要了解的一个信息是——</span></span></p>
<p><span style="color:#000000;"><span style="font-size:16px;">既然是这样,那么,在DA14531上,我们到底有多少的ROM(在STM32上我们已经很习惯称之为Flash)和 RAM可用。</span></span></p>
<p><span style="color:#000000;"><span style="font-size:16px;">注意,对于这时候的语境,我们说到ROM(FLASH),其实我们的意思是有多大的空间可以存储代码,有多大的空间可以用来作为堆栈?</span></span></p>
<p > </p>
<p ><span style="color:#000000;"><span style="font-size:16px;">对此,我们需要再简单地回顾一下C/C++程序在运行时,载入到RAM的结构。</span></span></p>
<p ><span style="color:#000000;"><span style="font-size:16px;">这一部分内容,你可能很熟悉——</span></span></p>
<p > </p>
<p ><span style="color:#000000;"><span style="font-size:16px;">简单地说,当一个C程序编译好后,它的CODE和用到的数据空间,大致如下</span></span></p>
<p > </p>
<p > </p>
<p ><span style="color:#000000;"><span style="font-size:16px;">分为</span></span></p>
<p ><strong><span style="color:#e74c3c;"><span style="font-size:16px;">Code ——通常称为代码区</span></span></strong></p>
<p ><strong><span style="color:#e74c3c;"><span style="font-size:16px;">RO-DATA ——通常称为常量区</span></span></strong></p>
<p ><strong><span style="color:#e74c3c;"><span style="font-size:16px;">RW-DATA ——它不同于RO,就在于它是可写的,当然也就不是常量</span></span></strong></p>
<p ><strong><span style="color:#e74c3c;"><span style="font-size:16px;">ZI-DATA ——其实它和RW-DATA是一回事,只不过,它的特点是,它会被初始化为0</span></span></strong></p>
<p ><span style="color:#000000;"><span style="font-size:16px;">所谓,ZI——就是 Zero Init的意思。</span></span></p>
<p ><span style="color:#000000;"><span style="font-size:16px;">这么说,你可能很蒙圈,没办法,把它们和你写的C语言联系到一起。</span></span></p>
<p > </p>
<p ><span style="color:#000000;"><span style="font-size:16px;">其实百度可以找到很多解释,但这里我可以简单举例说明</span></span></p>
<p ><span style="color:#000000;"><span style="font-size:16px;">所谓Code,它就是指你写的C语句,编译成对应的机器码;</span></span></p>
<p ><span style="color:#000000;"><span style="font-size:16px;">RO-DATA呢?</span></span></p>
<p ><span style="color:#000000;"><span style="font-size:16px;">RO-DATA主要包括哪些你初始化时用的数据;</span></span></p>
<p ><span style="color:#000000;"><span style="font-size:16px;">例如</span></span></p>
<p ><span style="color:#000000;"><span style="font-size:16px;">int a = 5;</span></span></p>
<p ><span style="color:#000000;"><span style="font-size:16px;">char s = “I love EEWORLD.\r\n”;</span></span></p>
<p ><span style="color:#000000;"><span style="font-size:16px;">这里,5 和 I love EEWORLD.\r\n 这两个用来初始化的内容,都将作为常量被存储在常量区</span></span></p>
<p > </p>
<p > </p>
<p ><span style="color:#000000;"><span style="font-size:16px;">还有const char s = 5;</span></span></p>
<p ><span style="color:#000000;"><span style="font-size:16px;">这个s也存在RO-DATA</span></span></p>
<p > </p>
<p ><span style="color:#000000;"><span style="font-size:16px;">至于RW-DATA 和 ZI-DATA,它们其实性质是类似的,惟一的区别是前面提到的,是否初始化为0。</span></span></p>
<p ><strong><span style="color:#e74c3c;"><span style="font-size:16px;">要注意的是——</span></span></strong></p>
<p ><strong><span style="color:#e74c3c;"><span style="font-size:16px;">上述RW-DATA ZI-DATA提到的变量都是全局变量、静态变量这种生存期涉及整个程序运行期间的变量。</span></span></strong></p>
<p ><span style="color:#000000;"><span style="font-size:16px;">对于局部变量,它们是存在于 栈 里的。</span></span></p>
<p > </p>
<p ><span style="color:#000000;"><span style="font-size:16px;">关于 栈 和 堆,这里不再详细展开。</span></span></p>
<p ><span style="color:#000000;"><span style="font-size:16px;">可以另行查阅。</span></span></p>
<p > </p>
<p ><span style="color:#000000;"><span style="font-size:16px;">但是,关于ZI-DATA,有一点是要注意的。</span></span></p>
<p ><span style="color:#000000;"><span style="font-size:16px;">那就是ZI-DATA中,同时包含了分配给栈的空间。</span></span></p>
<p ><span style="color:#000000;"><span style="font-size:16px;">其中的详细细节,我并不清楚,只在此做一个根据实际编译的实际例子说明——</span></span></p>
<p > </p>
<p align="left" ><span style="color:#000000;"><span style="font-size:16px;"> </span></span></p>
<p ><span style="color:#000000;"><span style="font-size:16px;">这个stack是默认分配的,暂时分了0x0700大小,也就是 1768 Bytes</span></span></p>
<p ><span style="color:#000000;"><span style="font-size:16px;"> </span></span></p>
<p ><span style="color:#000000;"><span style="font-size:16px;">所以这个这么简单的例程blinky里,一开始,ZI区就占用了1856 Bytes,实际上,其中,1768 Bytes是stack,实际上,这个例程只用了 88 Bytes。</span></span></p>
<p > </p>
<p ><span style="color:#000000;"><span style="font-size:16px;">而如果我们把栈缩小1K,变成 768Bytes</span></span></p>
<p ><span style="color:#000000;"><span style="font-size:16px;"> </span></span></p>
<p ><span style="color:#000000;"><span style="font-size:16px;"> </span></span></p>
<p ><span style="color:#000000;"><span style="font-size:16px;">可见,其他都没有变化,ZI-DATA相应也缩小了1024字节——1856 – 1024 = 832Bytes</span></span></p>
<p > </p>
<p ><span style="color:#000000;"><span style="font-size:16px;">详细的细节,可以查看编译生成的.map文件</span></span></p>
<p ><span style="color:#000000;"><span style="font-size:16px;"> </span></span></p>
<p ><span style="color:#000000;"><span style="font-size:16px;">而在map文件的末尾,我们可以看到总的情况</span></span></p>
<p ><span style="color:#000000;"><span style="font-size:16px;"> </span></span></p>
<p ><span style="color:#000000;"><span style="font-size:16px;">上述,ROM是不包括ZI-DATA的。</span></span></p>
<p ><span style="color:#000000;"><span style="font-size:16px;">而ROM正是以往,我们在STM32/51 MCU上,最终下载到片内FLASH的内容;</span></span></p>
<p ><span style="color:#000000;"><span style="font-size:16px;">而RW,则是在RAM里需要安排存储的内容;</span></span></p>
<p > </p>
<p ><span style="color:#000000;"><span style="font-size:16px;">那么,到了DA14531上,问题似乎变得更简单——</span></span></p>
<p ><span style="color:#000000;"><span style="font-size:16px;">既然,代码最终都载入到SysRAM里,也就意味着上述的 Code + RO + RW + ZI,就是要全部载入到SysRAM里的内容。</span></span></p>
<p ><span style="color:#000000;"><span style="font-size:16px;">也就是说,DA14531,ROM+RAM总共是 48KB</span></span></p>
<p > </p>
<p ><span style="color:#000000;"><span style="font-size:16px;">它没有明确区分 程序代码 和 数据区,但是,</span></span><strong><span style="color:#e74c3c;"><span style="font-size:16px;">考虑到片内OTP是32KB,</span></span></strong><span style="color:#000000;"><span style="font-size:16px;">那么,我们不妨这么认为,以后我们写的程序,程序(Code + RW)最终必须小于等于32KB,而RAM则预留16KB。</span></span></p>
<p > </p>
<p ><span style="color:#000000;"><span style="font-size:16px;">否则,我们就无法最终使用OTP方案实现量产。</span></span></p>
<p ><span style="color:#000000;"><span style="font-size:16px;">当然,即便你不惜外加FLASH芯片或者其他东西,无论如何,整个程序所有东西加起来,都必须小于48KB。</span></span></p>
<p>明天,我将继续更新几个主题</p>
<p>1-4、为节省IO口,如何使用SWD的两个引脚 SWDIO SWCLK同时实现 输出输入的 JLink RTT日志方法;</p>
<p>(DA14531和STM32比起来,略有一个不同的细节要注意,否则会无法输出内容)</p>
<p>1-5、对于死机时,如何使用JLINK,通过SWD进行现场信息分析的方法和所需工具</p>
<p>1-6、简单介绍 non-ble的 peripheral_project 的例程结构的简单介绍。</p>
<p><span style="color:#000000;"><span style="font-size:18px;">前面有个事情还忘了说——</span></span></p>
<p><strong><span style="font-size:24px;"><span style="color:#000000;">SmartBond Flash Programmer 和 烧录地址大小问题</span></span></strong></p>
<p> </p>
<p><span style="color:#000000;"><span style="font-size:18px;">如何把程序下载到板载的spi-flash里,也可以说,不只是在RAM里调试,而是真正固化到板上,不会掉电重启就梦回解放前。</span></span></p>
<p><span style="color:#000000;"><span style="font-size:18px;">这个事情,目前我没搞清楚怎么用我们喜闻乐见的J-Flash搞定——按道理也是可以的,不就是烧写Flash么。</span></span></p>
<p> </p>
<p><span style="color:#000000;"><span style="font-size:18px;">但现在我们有了一个现成工具。</span></span></p>
<p><span style="color:#000000;"><span style="font-size:18px;">DA提供的 SmartBond Flash Programmer</span></span></p>
<div><span style="color:#000000;"><span style="font-size:18px;"></span></span></div>
<p> </p>
<p><span style="color:#000000;"><span style="font-size:18px;">这玩意好处是,用起来特么简单,但缺点也是,特么简单——特么粗糙。</span></span></p>
<p><span style="color:#000000;"><span style="font-size:18px;">现在一一说说。</span></span></p>
<p><span style="color:#000000;"><span style="font-size:18px;">用起来简单,因为简单到几乎啥都不用说,你是个开发者一看就知道怎么用</span></span></p>
<p><span style="color:#000000;"><span style="font-size:18px;"></span></span></p>
<p><span style="color:#000000;"><span style="font-size:18px;">不过,不知道你们有没注意那段黄字。</span></span></p>
<p><span style="color:#000000;"><span style="font-size:18px;">这玩意很特么操蛋。</span></span></p>
<p><span style="color:#000000;"><span style="font-size:18px;">它要从瑞萨官方的服务器里拉一些什么东西升级。</span></span></p>
<p><span style="color:#000000;"><span style="font-size:18px;">但是,可能是没有科学上网的关系,这玩意就是不通,所以很烦。</span></span></p>
<p> </p>
<p><span style="color:#000000;"><span style="font-size:18px;">你每次重新打开这个软件,可能要岁月静好地登上大概一分多钟</span></span></p>
<p><span style="color:#000000;"><span style="font-size:18px;"> </span></span></p>
<p><span style="color:#000000;"><span style="font-size:18px;">对,就是它。</span></span></p>
<p> </p>
<p><span style="color:#000000;"><span style="font-size:18px;">这个玩意我试图想办法去掉,在合法但不科学上网的前提下解决问题</span></span></p>
<p><span style="color:#000000;"><span style="font-size:18px;">我试过</span></span></p>
<p><span style="color:#000000;"><span style="font-size:18px;">1、尝试找到关闭自动更新的地方——没找到,所以我说这个破软件,糙,特别的粗糙!</span></span></p>
<p><span style="color:#000000;"><span style="font-size:18px;">2、我尝试寻找官方是否又发布了新版本——没有,依然是当前的这个4140</span></span></p>
<p><span style="color:#000000;"><span style="font-size:18px;">3、我尝试卸载了再次安装,没用,它还给我继续卡——不过想想也是,在线升级的东西</span></span></p>
<p><span style="color:#000000;"><span style="font-size:18px;">——看来只能等下次科学上网的时候解决一下了。</span></span></p>
<p> </p>
<p><span style="color:#000000;"><span style="font-size:18px;">实在没办法,你可以像我一样,没事就不关它,实在不行,就静静地等上个一两分钟</span></span></p>
<p><span style="color:#000000;"><span style="font-size:18px;">岁月静好。</span></span></p>
<p> </p>
<p><span style="color:#000000;"><span style="font-size:18px;">关于这个小工具,最后还有一点要说的是——</span></span></p>
<p><span style="font-size:24px;"><span style="color:#000000;"><strong>关于烧录程序到spi Flash里的起始地址和结束地址,大小等问题</strong></span></span></p>
<p> </p>
<p><span style="color:#000000;"><span style="font-size:18px;">我同样翻了一下它的所有设置选项,都没有提及哪里设置和修改flash的烧录起始地址和结束的</span></span></p>
<p> </p>
<p><span style="color:#000000;"><span style="font-size:18px;">这里提一嘴,除了这个简易实用版的 SmartBond Flash Programmer,</span></span></p>
<p><span style="color:#000000;"><span style="font-size:18px;">DA官方还提供了另一个功能上看起来更为强大完整的工具</span></span></p>
<p><span style="color:#000000;"><span style="font-size:18px;">SmartBond Toolbox</span></span></p>
<p><span style="color:#000000;"><span style="font-size:18px;">当然,它也有不科学上网就要岁月静好等上一两分钟的破毛病。</span></span></p>
<p><span style="color:#000000;"><span style="font-size:18px;">不过它的界面看起来复杂一些,但我目前也没看文档,研究它有什么更进一步的用处。</span></span></p>
<p><span style="color:#000000;"><span style="font-size:18px;">我只记得,我看过它的简单介绍网页,没发现它有什么用向JLink看齐学习的地方。</span></span></p>
<p><span style="color:#000000;"><span style="font-size:18px;">这个工具似乎还只是烧录,但多了一些在线控制IO等一类的特殊功能而已。</span></span></p>
<p> </p>
<p><span style="color:#000000;"><span style="font-size:18px;">但对我来说,我想要的东西,它没有。</span></span></p>
<p> </p>
<p><font color="#000000"><span style="font-size: 18px;">回到烧录到spi Flash里的详细地址问题。</span></font></p>
<p><font color="#000000"><span style="font-size: 18px;">我们可以尝试烧录几个不同的固件,最终得到的结论,其实很简单——</span></font></p>
<p> </p>
<p><font color="#000000"><span style="font-size: 18px;">工具是根据要烧录的代码大小自动计算出要使用几个 flash sector</span></font></p>
<p> </p>
<p><font color="#000000"><span style="font-size: 18px;">因为每个sector都是4K。</span></font></p>
<p><font color="#000000"><span style="font-size: 18px;">当然这个代码大小不能直接看 hex或者bin的大小。</span></font></p>
<p><font color="#000000"><span style="font-size: 18px;">还是根据我们前面 Code + RO 的方式比较准确。</span></font></p>
<p> </p>
<p><font color="#000000"><span style="font-size: 18px;">这个地方为什么重要</span></font></p>
<p><font color="#000000"><span style="font-size: 18px;">因为我们使用的片外spi flash通常不只是拿来存储代码而已,还会拿来做其他用途。</span></font></p>
<p><font color="#000000"><span style="font-size: 18px;">因此,了解烧录程序的位置和大小很重要。</span></font></p>
<p> </p>
<p><span style="color:#000000;"><span style="font-size:18px;">当然,程序烧录的起点,自然清一色是 0地址。</span></span></p>
<p><span style="color:#000000;"><span style="font-size:18px;">从头开始</span></span></p>
<p><span style="color:#000000;"><span style="font-size:18px;"></span></span></p>
<p><span style="color:#000000;"><span style="font-size:18px;">这是我们前面提到过得简单 blinky 例程</span></span></p>
<p><span style="color:#000000;"><span style="font-size:18px;">它的Code不过区区2000多字节,RO也不大,一百多。</span></span></p>
<p><span style="color:#000000;"><span style="font-size:18px;">怎么加都不会超过4K,所以它只擦除了1个sector。 0到 0xFFF</span></span></p>
<p> </p>
<p><span style="color:#000000;"><span style="font-size:18px;"> 而这个带蓝牙的例程就不同了。</span></span></p>
<p><span style="color:#000000;"><span style="font-size:18px;">它的Code就有 16000多字节,达14K,另外,它的RO也大,有2000多字节,加起来超过16K字节。</span></span></p>
<p><span style="color:#000000;"><span style="font-size:18px;">因此,它使用了5个sector</span></span></p>
<p><span style="color:#000000;"><span style="font-size:18px;">同样,当然也是从0地址开始。</span></span></p>
<p> </p>
<p><span style="color:#000000;"><span style="font-size:18px;">具体你们可以自己试试。</span></span></p>
<p> </p>
<p><span style="color:#000000;"><span style="font-size:18px;">所以,在暂时不清楚OTA的方式的情况下,我们可以预留前48K全部给 程序代码存储。</span></span></p>
<p><span style="color:#000000;"><span style="font-size:18px;">至于考虑上OTA,也就是多给48K就是了。</span></span></p>
<p> </p>
<p><span style="color:#000000;"><span style="font-size:18px;">对于一个动不动上MB的spi Flash而言,不过区区100KB不到,也没多大点事</span></span></p>
<p> </p>
<p> </p>
<p><span style="color:#000000;"><span style="font-size:18px;">现在说一下用 JLink RTT 替代常用的 串口打印调试信息 的事情</span></span></p>
<p><span style="color:#000000;"><span style="font-size:18px;">JLink大法是真的好——以前太年轻,又贪图方便不担心盗版问题。</span></span></p>
<p> </p>
<p><span style="color:#000000;"><span style="font-size:18px;">其实,盗版就盗版,怎么了。</span></span></p>
<p><span style="color:#000000;"><span style="font-size:18px;">盗版吃德国佬全家大米了吗。</span></span></p>
<p> </p>
<p><span style="color:#000000;"><span style="font-size:18px;">说回正事。</span></span></p>
<p> </p>
<p><span style="color:#000000;"><span style="font-size:18px;">首先,因为DA14531的io口实在太稀缺了。</span></span></p>
<p><span style="color:#000000;"><span style="font-size:18px;">DA14531有两个封装,WLCSP(17pin) 和 FCGQFN(24pin)</span></span></p>
<p><span style="color:#000000;"><span style="font-size:18px;"></span></span></p>
<p><span style="color:#000000;"><span style="font-size:18px;"> </span></span></p>
<p><span style="color:#000000;"><span style="font-size:18px;">无论是哪个,即使是我做的这么一个非常个性放飞自我,简化的手环套件,目前,我还没加入 gsensor</span></span></p>
<p><span style="color:#000000;"><span style="font-size:18px;">它就已经用光了我所有的io。</span></span></p>
<p><span style="color:#000000;"><span style="font-size:18px;">这还是我用JLINK RTT替代了串口的关系。</span></span></p>
<p> </p>
<p><span style="color:#000000;"><span style="font-size:18px;">总之,这颗MCU的IO口非常缺少。</span></span></p>
<p><span style="color:#000000;"><span style="font-size:18px;">但是,调试和打印又是我们非常必不可少的功能。</span></span></p>
<p> </p>
<p><span style="color:#000000;"><span style="font-size:18px;">因此,在这里,我强烈推荐,以后都用SWD提供的RTT功能,全面替代传统的串口调试输出。</span></span></p>
<p> </p>
<p><span style="color:#000000;"><span style="font-size:18px;">RTT和SWO是有一点不同的,除了实现方式和性能上的一些目前我们不太关心的差别。</span></span></p>
<p><span style="color:#000000;"><span style="font-size:18px;">其实最重要的是,SWO只能输出,而RTT还能输入,是一个全功能的,除了目前官方版本不支持打印浮点数以外。</span></span></p>
<p><span style="color:#000000;"><span style="font-size:18px;">它是一个非常完美的可以完全代替 printf scanf的输入输出功能。</span></span></p>
<p><span style="color:#000000;"><span style="font-size:18px;">而且不额外增加任何io口资源。</span></span></p>
<p> </p>
<p><span style="color:#000000;"><span style="font-size:18px;">这一点,只支持SWO的 ST-LINK就稍逊一筹了——当然,我说的是只使用四线SWD的情况下。</span></span></p>
<p><span style="color:#000000;"><span style="font-size:18px;">因为ST-LINK本身也支持JTAG和其他的IO口。</span></span></p>
<p><span style="color:#000000;"><span style="font-size:18px;">它在JTAG模式下,同样可以支持其他的输入输出功能。</span></span></p>
<p> </p>
<p><span style="color:#000000;"><span style="font-size:18px;">但我们现在缺的就是IO,要的就是四线SWD。</span></span></p>
<p> </p>
<p><span style="color:#000000;"><span style="font-size:18px;">关于具体的方式,我们下一贴说。</span></span></p>
<p><span style="color:#000000;"><span style="font-size:18px;"> </span></span></p>
<p> </p>
本帖最后由 辛昕 于 2024-1-18 16:00 编辑
<p><span style="color:#000000;"><span style="font-size:24px;">JLink的RTT如何使用</span></span></p>
<p> </p>
<p><span style="color:#000000;"><span style="font-size:18px;">其实,这个话题,在百度上一搜一大把,本不需要多说。</span></span></p>
<p><span style="color:#000000;"><span style="font-size:18px;">但是,有两点,却是很多文章没有提及的。</span></span></p>
<p> </p>
<p><span style="color:#000000;"><span style="font-size:18px;">这里会特别补充一下</span></span></p>
<p><span style="color:#000000;"><span style="font-size:18px;">1、DA14531芯片在使用的时候,不像STM32,不能使用Auto 自动识别地址;</span></span></p>
<p><span style="color:#95a5a6;"><span style="font-size:18px;">2、通过Telnet的方式,用其他日志工具连接,以实现更强大的日志记录功能;(下一楼)</span></span></p>
<p> </p>
<p><span style="color:#000000;"><span style="font-size:18px;">下面一一道来。</span></span></p>
<p> </p>
<p><span style="color:#000000;"><span style="font-size: 18px;">基本的RTT使用方法不多说,可以自行搜索百度,这里只简单提及步骤:</span></span></p>
<p><strong><span style="color:#e74c3c;"><span style="font-size:24px;">1、在JLink安装目录下,找到RTT的源码;</span></span></strong></p>
<p><strong><span style="font-size:24px;"><span style="color:#e74c3c;">2、源码加入项目编译;</span></span></strong></p>
<p><span style="color:#000000;"><span style="font-size: 18px;"> 当然还要顺带修改好头文件搜索路径啥的。</span></span></p>
<p><span style="color:#000000;"><span style="font-size: 18px;"> 这里同样要提一句——是不需要加入 </span></span></p>
<p><font color="#000000"><span style="font-size: 18px;"> </span></font> </p>
<p><span style="color:#000000;"> <span style="font-size:18px;"> 加入这个东西,编译会提示链接失败,少了什么东西。</span></span></p>
<p><span style="color:#000000;"><span style="font-size:18px;"> 这个东西,我也没去细究,因为我不加,也照样正常的用RTT 输出输出。</span></span></p>
<p> </p>
<p><span style="color:#000000;"><span style="font-size:18px;"> 但想来这个东西必然是有些和keil本身有关的一些特殊功能,只是暂时没用到。</span></span></p>
<p> </p>
<p><span style="font-size:24px;"><strong><span style="color:#e74c3c;">第二个问题,到底是加KEIL.c还是 GCC.c的问题——</span></strong></span></p>
<p> </p>
<p><span style="color:#000000;"><span style="font-size:18px;"> 前面我就说过,Keil5现在默认使用的是 AC6的编译器,而不再是AC5的编译器。</span></span></p>
<p><span style="color:#000000;"><span style="font-size:18px;"> 这会造成一些使用上的区别,例如,后面在移植FreeRTOS的时候,使用的不是 Keil/RVDS下的port文件</span></span></p>
<p><span style="color:#000000;"><span style="font-size:18px;">而是GCC。</span></span></p>
<p><span style="color:#000000;"><span style="font-size:18px;"> 所以,由此联想,我突然想,也许这里该调用的不是 KEIL.c而是GCC.c</span></span></p>
<p><span style="color:#000000;"><span style="font-size:18px;"> 但这个问题,我暂时无力关心,也用不上,留待后续验证,并弄清楚,这个玩意是拿来实现什么功能的。</span></span></p>
<p> </p>
<p><span style="color:#000000;"><span style="font-size:18px;"> 我现在有一个原则,要尽可能地全面挖掘JLink Keil5 等工具链的用途,包括后面,我会提到用于非调试阶段使用的</span></span></p>
<p><span style="color:#000000;"><span style="font-size:18px;">Ozone工具,也是一个SEGGER提供的类似gdb的调试工具。</span></span></p>
<p><span style="color:#000000;"><span style="font-size:18px;"> 这里我给那些想现在马上就研究的人一个建议,其实方法很简单:你可以直接尝试搜索 <strong>SEGGER_RTT_Syscalls_KEIL.c</strong> 这个关键词...</span></span></p>
<p> </p>
<p><strong><span style="color:#e74c3c;"><span style="font-size:24px;">3、打开 JLink RTT Viewer,对于DA14531,还要设置SEGGER_RTT的map地址</span></span></strong></p>
<p> </p>
<p><span style="font-size:18px;"> </span> </p>
<p><span style="color:#000000;"><span style="font-size:18px;">对于STM32,直接选 Auto Detection 啥事没有,但对于DA14531幺蛾子就是多,它得选 Address,否则你就啥都看不到,还以为坏了</span></span></p>
<p><span style="color:#000000;"><span style="font-size:18px;">那么,这个地址在哪里呢?</span></span></p>
<p><span style="color:#000000;"><span style="font-size:18px;">在map里</span></span></p>
<p></p>
<p><span style="color:#000000;"><span style="font-size:18px;">哦,上下两图对不上是吧,不要在意这种细节。</span></span></p>
<p><span style="color:#000000;"><span style="font-size:18px;">你懂意思就行。</span></span></p>
<p><span style="color:#000000;"><span style="font-size:18px;">毕竟我切来切去好几个不同的项目,是这样子的。</span></span></p>
<p><span style="color:#000000;"><span style="font-size:18px;">所以</span></span><strong><span style="color:#e74c3c;"><span style="font-size:18px;">发布量产固件,map是一个非常重要的文件,必须妥善保存在固件包</span></span></strong><span style="color:#000000;"><span style="font-size:18px;">里就是这个道理,它还会在我们调试死机等分析现场问题时的重要依据。</span></span></p>
<p> </p>
<p><span style="color:#000000;"><span style="font-size:18px;">本来我还想把使用XShell 来实现日志记录加上时间戳的一并写了,但3点就要腾讯视频面试了,一会,下楼再写。</span></span></p>
<p> </p>
<p> </p>
<p>昕昕好厉害 先占楼在看</p>
<p><span style="color:#000000;"><strong><span style="font-size:24px;">通过Telnet的方式,用其他日志工具连接,以实现更强大的日志记录功能</span></strong></span></p>
<p> </p>
<p><font color="#000000"><span style="font-size: 18px;">首先上一张图,就是 J-Link RTT Viewer的截图</span></font></p>
<p> </p>
<p> </p>
<p><span style="color:#000000;"><span style="font-size:18px;">粗糙,特别的粗糙——</span></span></p>
<p><span style="color:#000000;"><span style="font-size:18px;">不单纯是因为界面不美丽的事情,在程序开发和调试工具上,我向来(就)不是一个颜狗。</span></span></p>
<p><span style="color:#000000;"><span style="font-size:18px;">但是,它最大的问题还不是颜值不颜值的问题,主要是它用起来功能很不强大。</span></span></p>
<p> </p>
<p><span style="color:#000000;"><span style="font-size:18px;">事实上,我现在很喜欢用XShell做日志记录工具。</span></span></p>
<p><span style="color:#000000;"><span style="font-size:18px;">别的功能不说,用XShell做日志记录,可以自动给每条记录添加时间戳,这对于长期运行日志和分析问题是极其有帮助的。</span></span></p>
<p><span style="color:#000000;"><span style="font-size:18px;"> </span></span></p>
<p><span style="color:#000000;"><span style="font-size:18px;">但是,J-Link RTT Viewer不行。</span></span></p>
<p><span style="color:#000000;"><span style="font-size:18px;">实际上,J-Link系列工具链原生提供的另外两个RTT工具</span></span></p>
<p><span style="color:#000000;"><span style="font-size:18px;">J-Link RTT Logger 和 J-Link RTT Client 实际上也不具备这个功能——当然,这两个东西本来就不是单纯拿来做日志工具的。</span></span></p>
<p><span style="color:#000000;"><span style="font-size:18px;"> </span></span></p>
<p><span style="color:#000000;"><span style="font-size:18px;">专业的事情要交给专业的工具做。</span></span></p>
<p> </p>
<p><span style="color:#000000;"><span style="font-size:18px;">现在介绍一下 XShell 如何通过 Telnet方式连接 J-Link RTT 记录日志。</span></span></p>
<p><span style="color:#000000;"><span style="font-size:18px;">这里之所以要详细说明,是因为在这个 案例里,有几个地方需要注意,否则就会失败。</span></span></p>
<p> </p>
<p><span style="color:#000000;"><span style="font-size:18px;">1、XShell新建 Telnet连接</span></span></p>
<p><span style="color:#000000;"><span style="font-size:18px;"> </span></span></p>
<p> </p>
<p><span style="color:#000000;"><span style="font-size:18px;"> </span></span></p>
<p><span style="color:#000000;"><span style="font-size:18px;">2、JLink RTT 默认的 ip地址和端口号</span></span></p>
<p><span style="color:#000000;"><span style="font-size:18px;">IP地址自然是 本地回环地址 127.0.0.1 端口号默认是 19021</span></span></p>
<p><span style="color:#000000;"><span style="font-size:18px;"> </span></span></p>
<p><span style="color:#000000;"><span style="font-size:18px;">3、特别注意——默认XShell 的 Telnet 选项有个地方要改,否则会出现 能连接,却不能正常显示内容</span></span></p>
<p><span style="color:#000000;"><span style="font-size:18px;">【注:后续我发现这个设置有时不设置也可以,不知道为何】</span></span></p>
<p><span style="color:#000000;"><span style="font-size:18px;">——但假如你出现不能正常打印的话,就设置了一下。</span></span></p>
<p><span style="color:#000000;"><span style="font-size:18px;"> </span></span></p>
<p> </p>
<p><span style="color:#000000;"><span style="font-size:18px;"> </span></span></p>
<p> </p>
<p><span style="color:#000000;"><span style="font-size:18px;">4、同样很关键</span></span></p>
<p><span style="color:#000000;"><span style="font-size:18px;">我们在XShell 是以一个 Telnet客户端接入,既然如此,那么,那就肯定需要运行一个 Telnet服务器。</span></span></p>
<p><span style="color:#000000;"><span style="font-size:18px;">而这个Telnet服务器,在有一个Jlink接入并激活到工作状态时就会自动生成。</span></span></p>
<p> </p>
<p><span style="color:#000000;"><span style="font-size:18px;">那,怎么叫 “激活到工作状态”呢?</span></span></p>
<p><span style="color:#000000;"><span style="font-size:18px;">显然,JLink只是插入电脑不算。</span></span></p>
<p> </p>
<p><span style="color:#000000;"><span style="font-size:18px;">有两种方式,就可以启动这个 Telnet服务端,允许被接入。</span></span></p>
<p><span style="color:#000000;"><span style="font-size:18px;">1、Keil IAR等在调试时;</span></span></p>
<p><span style="color:#000000;"><span style="font-size:18px;">2、我们通过上述的 J-Link RTT Viewer连接时;</span></span></p>
<p><span style="color:#000000;"><span style="font-size:18px;">但这里要说明一点。</span></span></p>
<p><span style="color:#000000;"><span style="font-size:18px;">对于DA14531而言,由于它需要指定 RTT Address,就是下图这个东西</span></span></p>
<p><span style="color:#000000;"><span style="font-size:18px;"> </span></span></p>
<p><span style="color:#000000;"><span style="font-size:18px;">所以,只是Keil进入调试状态时,也不行——会出现,能够连接,但不正常打印。</span></span></p>
<p><span style="color:#000000;"><span style="font-size:18px;">因此,也需要打开 J-Link RTT Viewer。</span></span></p>
<p> </p>
<p><span style="color:#000000;"><span style="font-size:18px;">最后一步——XShell的日志记录 和 如何记录日志。</span></span></p>
<p> </p>
<p> </p>
<p><span style="color:#000000;"><span style="font-size:18px;">选择 “当前会话属性”</span></span></p>
<p> </p>
<p><span style="color:#000000;"><span style="font-size:18px;">选择 日志记录</span></span></p>
<p><span style="color:#000000;"><span style="font-size:18px;">同时 在 时间戳 下面</span></span></p>
<p><span style="color:#000000;"><span style="font-size:18px;"> 写入日志文件 处 打√</span></span></p>
<p> </p>
<p><span style="color:#000000;"><span style="font-size:18px;">同时,在格式那里选择和设置</span></span></p>
<p><span style="color:#000000;"><span style="font-size:18px;">如果要把时间戳精确到 小数点后3位,即,毫秒</span></span></p>
<p> </p>
<p><span style="color:#000000;"><span style="font-size:18px;">参考 后面的书写方式</span></span></p>
<p><span style="color:#000000;"><span style="font-size:18px;">要在最后 加上 “%N”</span></span></p>
<p> </p>
<p><font color="#000000"><span style="font-size: 18px;">如何存储日志</span></font></p>
<p> </p>
<p><span style="color:#000000;"><span style="font-size:18px;">右键,选择 日志-- 启动</span></span></p>
<p><span style="color:#000000;"><span style="font-size:18px;">剩下就简单了</span></span></p>
<p><span style="color:#000000;"><span style="font-size:18px;">新建日志文件名字 和 选择存储位置</span></span></p>
<p> </p>
常见泽1 发表于 2024-1-18 18:28
昕昕好厉害 先占楼在看
<p>荒淫,荒淫,无任荒淫</p>
<p><span style="font-size:16px;">接下来简单介绍一个 JLink下用来调试诸如 DUMP 死机等问题的工具</span></p>
<p><span style="font-size:16px;">这个,其实不仅限于 DA14531,是一个基于 JLink 的通用工具</span></p>
<p><span style="font-size:16px;">——这也是为什么,我坚持要开放 SWD的两个IO,不仅是为了下载,也是为了调试。</span></p>
<p> </p>
<p><span style="font-size:16px;">说到调试程序,一般来说,我们都是以输出日志的方式来调试。</span></p>
<p><span style="font-size:16px;">这个时候,用串口也没什么问题。</span></p>
<p> </p>
<p><span style="font-size:16px;">但是,一旦出现死机或者DUMP之类的问题,整个系统卡死,无法运行的时候。</span></p>
<p><span style="font-size:16px;">就没办法用串口这种方式输出了。</span></p>
<p> </p>
<p><span style="font-size:16px;">而此时,多半也是出现 DUMP,或者ARM这类器件里,会进入保护性的 HardFault 一类的——它通常是个死循环之类的。</span></p>
<p> </p>
<p><span style="font-size:16px;">而这个时候,我们通常要做的事情就是</span></p>
<p><span style="font-size:16px;">1、找到卡死前最后运行的语句、函数;</span></p>
<p><span style="font-size:16px;">2、查看当前的一些重要寄存器的内容,或者我们关心的一些重要变量;</span></p>
<p> </p>
<p><span style="font-size:16px;">——说句实话,我比较少用JLink做这种调试,以前在移远的时候,基于模组芯片原厂提供的TRACE32工具,我有做过类似的分析。</span></p>
<p><span style="font-size:16px;">所以,这里,我只是先提供相应的工具,以及一些基本使用。</span></p>
<p> </p>
<p><span style="font-size:16px;">当然,昨天我在测试FreeRTOS的基本任务时,其实我发现一开始我死机过,所以后面如果时间允许,我会尝试拿那个环境来做一下举例说明。</span></p>
<p> </p>
<p><span style="font-size:16px;">也作为我自己这方面的实操练习。</span></p>
<p> </p>
<p> </p>
<p> </p>
<p><span style="color:#000000;"><span style="font-size:18px;">上述的两种基础操作</span></span></p>
<p><span style="color:#000000;"><span style="font-size:18px;">如果是在开放时,用Keil5 MDK IAR等开发环境,相信你很熟悉,不用我说你也知道。</span></span></p>
<p><span style="color:#000000;"><span style="font-size:18px;">不过,本着送佛送到西,打人打到死的原则,即使你们懂,我也准备发一波图。</span></span></p>
<p> </p>
<p><span style="color:#000000;"><span style="font-size:18px;">很显然,所有要看的东西,当然都在 View 里</span></span></p>
<p><span style="color:#000000;"><span style="font-size:18px;"> </span></span></p>
<p><span style="color:#000000;"><span style="font-size:18px;">但,你也不能乱看。</span></span></p>
<p><span style="color:#000000;"><span style="font-size:18px;">比如我前面说的,我来来去去,一般就看俩地方。</span></span></p>
<p> </p>
<p><span style="color:#000000;"><span style="font-size:18px;">第一,最重要的,当然是PC,PC,还是他妈的PC</span></span></p>
<p><span style="color:#000000;"><span style="font-size:18px;"> </span></span></p>
<p><span style="color:#000000;"><span style="font-size:18px;">不过你可能很奇怪,没事看什么PC?</span></span></p>
<p><span style="color:#000000;"><span style="font-size:18px;">还有这个什么 07FC00B4又是个什么鬼?</span></span></p>
<p><span style="color:#000000;"><span style="font-size:18px;">这时我们就需要祭上 map 了</span></span></p>
<p><span style="color:#000000;"><span style="font-size:18px;">当然,其实,在 DEBUG的时候,谁还那么低级的去看 map</span></span></p>
<p><span style="color:#000000;"><span style="font-size:18px;">直接搞到 反汇编界面去</span></span></p>
<p><span style="color:#000000;"><span style="font-size:18px;"> </span></span></p>
<p><span style="color:#000000;"><span style="font-size:18px;">没错,是他,是他,就是他。</span></span></p>
<p> </p>
<p><span style="color:#000000;"><span style="font-size:18px;">其次,第二件,看什么呢?</span></span></p>
<p><span style="color:#000000;"><span style="font-size:18px;">嗯,看memory,看哪的memory呢?说了,不要乱看。</span></span></p>
<p><span style="color:#000000;"><span style="font-size:18px;">比如我们前面分析了,当代码最终载入 SysRAM后,会将地址重映射成0</span></span></p>
<p><span style="color:#000000;"><span style="font-size:18px;">可是,0那一块是啥?是Code啊,你说你没事看什么Code</span></span></p>
<p> </p>
<p><span style="color:#000000;"><span style="font-size:18px;">所以,还是不对,那么,到底看哪呢?</span></span></p>
<p><span style="color:#000000;"><span style="font-size:18px;">这回真的只能看map了......</span></span></p>
<p><span style="color:#000000;"><span style="font-size:18px;"> </span></span></p>
<p><span style="color:#000000;"><span style="font-size:18px;">但老实说,因为我这就是一个例程,简单至极,没有什么我很关心的变量、数组。</span></span></p>
<p><span style="color:#000000;"><span style="font-size:18px;">而我对FreeRTOS的内部实现又不熟悉,我也没什么函数想看。</span></span></p>
<p> </p>
<p><span style="color:#000000;"><span style="font-size:18px;">但是,很显然,在这里,任何函数,任何变量(除了局部变量这种在堆栈上的东西)</span></span></p>
<p><span style="color:#000000;"><span style="font-size:18px;">你统统都可以看到它的地址。</span></span></p>
<p><span style="color:#000000;"><span style="font-size:18px;">基本上也就是说,你想看什么,就看什么。</span></span></p>
<p> </p>
<p><span style="color:#000000;"><span style="font-size:18px;">剩下还有什么可以看呢?</span></span></p>
<p><span style="color:#000000;"><span style="font-size:18px;">我说了嘛,其实我很少这么深度调试过这么底层的东西,所以,我也不知道.........</span></span></p>
<p><span style="color:#000000;"><span style="font-size:18px;">那么,如果不是在DEBUG开发的时候,突然发生了什么奇怪的死机或者HALT一类的问题,你又怎么整呢?</span></span></p>
<p><span style="color:#000000;"><span style="font-size:18px;">如果你想知道当时的现场状况,显然你不能复位,更不能拿出KEIL,怼上,重新DEBUG。</span></span></p>
<p> </p>
<p><span style="color:#000000;"><span style="font-size:18px;">这个时候,你有两个选择</span></span></p>
<p><span style="color:#000000;"><span style="font-size:18px;">1、J-Link COMMANDER</span></span></p>
<p> </p>
<p><span style="color:#000000;"><span style="font-size:18px;">2、J-Link OZONE</span></span></p>
<p><span style="color:#000000;"><span style="font-size:18px;">这两个东西做的其实是一件事情,就是以一些和GDB很类似的命令,同时严格来说,其实和我们前面在DEBUG时所做的事情很类似</span></span></p>
<p> </p>
<p><span style="color:#000000;"><span style="font-size:18px;">下断点啦</span></span></p>
<p><span style="color:#000000;"><span style="font-size:18px;">单步运行了</span></span></p>
<p><span style="color:#000000;"><span style="font-size:18px;">查看变量了</span></span></p>
<p><span style="color:#000000;"><span style="font-size:18px;">看memory了</span></span></p>
<p><span style="color:#000000;"><span style="font-size:18px;">看PC跑到哪去了.......</span></span></p>
<p><span style="color:#000000;"><span style="font-size:18px;">以下,是我截图的 COMMANDER 一系列和这种调试有关的命令,不知道你们怎么想,反正我怎么看怎么像GDB干的那些事</span></span></p>
<p> </p>
<p> </p>
<p><span style="color:#000000;"><span style="font-size:18px;">你可能会问我,为什么这次我是上网百度截图的?</span></span></p>
<p><span style="color:#000000;"><span style="font-size:18px;">因为我没这么惨过嘛.......半路死了还要拿回来现场调试?</span></span></p>
<p><span style="color:#000000;"><span style="font-size:18px;">太惨了。</span></span></p>
<p><span style="color:#000000;"><span style="font-size:18px;">说起来我真的干这种事,还是在移远做通信模块ODM开发的时候,一般我也是吼模组的人做。</span></span></p>
<p><span style="color:#000000;"><span style="font-size:18px;">他们不做,我自己也就用TRACE32自己看。</span></span></p>
<p><span style="color:#000000;"><span style="font-size:18px;">但那东西都是封装好了的图形界面啊,当然没那么惨了.......</span></span></p>
<p><span style="color:#000000;"><span style="font-size:18px;">不过我答应你——只要你们给我一键三连+关注</span></span></p>
<p> </p>
<p><span style="color:#000000;"><span style="font-size:18px;">后面我写完FreeRTOS的移植验证,我会找时间亲自体验一把的。</span></span></p>
<p><span style="color:#000000;"><span style="font-size:18px;">最后,关于这个话题,我继续本着打人打到脑残的原则。</span></span></p>
<p><span style="color:#000000;"><span style="font-size:18px;">把 J-Link OZONE 的事情也说说</span></span></p>
<p><span style="color:#000000;"><span style="font-size:18px;">不过我先说明,和J-Link Commander类似,我真的没实际干过。</span></span></p>
<p><span style="color:#000000;"><span style="font-size:18px;">我只是SHOW一下这些美妙的工具。</span></span></p>
<p><span style="color:#000000;"><span style="font-size:18px;">那么,以后在某个你呼天抢地,没人救你,你只能凭借自己的直觉和经验自己调试问题的时候</span></span></p>
<p><span style="color:#000000;"><span style="font-size:18px;">也许你会因为想起今天有人和你说过那么一个工具而突然痛苦流泪,感动到.......</span></span></p>
<p> </p>
<p><span style="color:#000000;"><span style="font-size:18px;">不要问我为什么知道这些.......</span></span></p>
<p> </p>
<p><span style="color:#000000;"><span style="font-size:18px;">OZONE是SEGGER出的,免费,自己去官网下.......</span></span></p>
<p> </p>
<p><span style="color:#000000;"><span style="font-size:18px;"></span></span></p>
<p> </p>
<p><span style="color:#000000;"><span style="font-size:18px;">这一步可以不选elf或者hex新固件</span></span></p>
<p><span style="color:#000000;"><span style="font-size:18px;">——我说了嘛,因为我们现在是要调试现有的板子里的东西么</span></span></p>
<p><span style="color:#000000;"><span style="font-size:18px;"> </span></span></p>
<p><span style="color:#000000;"><span style="font-size:18px;">好了,现在已经进来了</span></span></p>
<p><span style="color:#000000;"><span style="font-size:18px;"> VIEW这个东西一如既往地亲切熟悉</span></span></p>
<p><span style="color:#000000;"><span style="font-size:18px;"></span></span></p>
<p> </p>
<p><span style="color:#000000;"><span style="font-size:18px;">当然,最重要的,你还是要首先进入 DEBUG</span></span></p>
<p><span style="color:#000000;"><span style="font-size:18px;"> </span></span></p>
<p><span style="color:#000000;"><span style="font-size:18px;"> </span></span></p>
<p><span style="color:#000000;"><span style="font-size:18px;">显然</span></span></p>
<p><span style="color:#000000;"><span style="font-size:18px;"> </span></span></p>
<p><span style="color:#000000;"><span style="font-size:18px;">现在我们肯定不想选择第一个,不然KEIL MDK是死的嘛.......</span></span></p>
<p><span style="color:#000000;"><span style="font-size:18px;">所以要选择 第二个或者第三个。</span></span></p>
<p><span style="color:#000000;"><span style="font-size:18px;">我喜欢第二个</span></span></p>
<p> </p>
<p><span style="color:#000000;"><span style="font-size:18px;">OK,进来了</span></span></p>
<p><span style="color:#000000;"><span style="font-size:18px;"> </span></span></p>
<p><span style="color:#000000;"><span style="font-size:18px;">前面我们说过,SysRAM会被重新映射到0么,但是我也说过,我没事看Code干什么?</span></span></p>
<p> </p>
<p><span style="color:#000000;"><span style="font-size:18px;">我就说了它真的很像 GDB</span></span></p>
<p><span style="color:#000000;"><span style="font-size:18px;"> </span></span></p>
<p><span style="color:#000000;"><span style="font-size:18px;">因为我刚才进来是 running状态,所以,你可以先停下来,然后单步......或者跑进函数,或者跑步来.......</span></span></p>
<p><span style="color:#000000;"><span style="font-size:18px;"> </span></span></p>
<p><span style="color:#000000;"><span style="font-size:18px;"> </span></span></p>
<p><span style="color:#000000;"><span style="font-size:18px;">哦,原来这个图标是这个意思,我还想最边边那个啥意思,跑到上一步?有点诡异,原来这个才是跑进去,跑出来的意思......</span></span></p>
<p> </p>
<p><span style="color:#000000;"><span style="font-size:18px;"> </span></span></p>
<p><span style="color:#000000;"><span style="font-size:18px;">然后又是我们熟悉的 </span></span></p>
<p><span style="color:#000000;"><span style="font-size:18px;">寄存器了——看PC</span></span></p>
<p><span style="color:#000000;"><span style="font-size:18px;">我们熟悉的 Disassembly了</span></span></p>
<p><span style="color:#000000;"><span style="font-size:18px;"> 话说回来,这个function,在这个时候我就真的不知道怎么用了......</span></span></p>
<p> </p>
<p> </p>
<p><span style="color:#000000;"><span style="font-size:18px;"> </span></span></p>
<p> </p>
<p>啊,其实还有一个,就是简单介绍一下例程</p>
<p> </p>
<p>其实,真的挺简单,不过,算了,后面再写,今天我写地快吐了.......</p>
<p><img height="52" src="https://bbs.eeworld.com.cn/static/editor/plugins/hkemoji/sticker/facebook/wanwan68.gif" width="48" /><img height="48" src="https://bbs.eeworld.com.cn/static/editor/plugins/hkemoji/sticker/facebook/wanwan79.gif" width="52" /><img height="48" src="https://bbs.eeworld.com.cn/static/editor/plugins/hkemoji/sticker/facebook/wanwan79.gif" width="52" /><img height="48" src="https://bbs.eeworld.com.cn/static/editor/plugins/hkemoji/sticker/facebook/wanwan88.gif" width="59" /><img height="48" src="https://bbs.eeworld.com.cn/static/editor/plugins/hkemoji/sticker/facebook/wanwan88.gif" width="59" /></p>
<p><img height="48" src="https://bbs.eeworld.com.cn/static/editor/plugins/hkemoji/sticker/facebook/congra.gif" width="48" /> 大佬厉害, 受益匪浅</p>
<p>历程呢。很多程序编起来要库函数吧。没有库编起来是不是很复杂,比如驱动一个I2C?</p>
页:
[1]
2