本应用笔记讨论了MAX-IDE为MAXQ®微控制器上的应用编程提供的代码和数据段工具。代码和数据段机制提供了一种在数据存储器中自动声明变量位置并使用起始值初始化这些变量的方法。然后,可以使用应用程序代码将这些变量值缓存在闪存中,并根据需要还原它们。这种方法允许基于汇编的应用利用MAX-IDE提供的数据段自动加载,同时无论微控制器是否连接到JTAG调试器,都能始终如一地运行。MAXQ2000微控制器评估板用于演示方法,文中提供了代码示例。
概述
MAXQ汇编应用中的变量可以存储在工作寄存器(如累加器A[0]至A[15])或数据存储器(SRAM)中。将变量存储在数据存储器中为应用程序变量提供了更大的工作区域,但确实需要额外的访问时间。
MaxQAsm 汇编器和 MAX-IDE 环境提供了一种声明单独代码和数据段的机制,并为每个段生成单独的十六进制输出文件。在运行时,MAX-IDE自动将数据段文件加载到程序存储器(通常为闪存)中,将数据段文件加载到数据存储器(通常为RAM)中。但是,由于数据存储器是易失性的,一旦微控制器断电,数据段内容将不会保持不变。
本应用笔记首先使用MAXQ2000评估(评估)板演示如何在初始应用运行期间将这些预加载的数据存储器值保存在闪存中,然后在微控制器随后再次上电时如何刷新闪存中的数据段值。这个两步过程允许使用相同的数据段机制来声明和初始化变量,无论应用程序是在开发中(连接到JTAG适配器和MAX-IDE)还是在现场运行。
本应用笔记的演示代码为MAXQ2000微控制器和MAXQ2000评估板编写,但所示代码和原理适用于任何具有可重写程序闪存的MAXQ20微控制器。
MAX-IDE环境的最新安装包和文档可免费下载。
最大集成开发台安装
MAXQ磁芯组装指南
开发工具指南
变量和存储位置
嵌入式应用程序通常需要一定的工作空间来存储状态信息、配置设置、中间工作值、循环计数器和计算结果。存储在此工作空间中的值通常称为变量,并具有以下特征。
它们是暂时的。如果应用程序因电源故障或重置而中断,则不需要保存它们。
它们经常被访问和更新。它们必须存储在可以快速读取或写入的位置;位置的写入次数不得有限制。
它们通常具有定义的初始值。用户的代码必须在应用程序开始时将它们设置为特定值。
在用 C 或其他高级语言编写并编译为汇编代码的应用程序中,编译器通常自动处理变量的空间分配(以及将变量初始化为预定义起始值的过程)。在这种情况下,用户只需要声明变量、其类型和(可选)其初始值。编译器处理其余部分。
unsigned int c = 0x1234;
但是,当直接用MAXQ汇编语言编写应用程序时,必须明确地为变量分配空间并将变量设置为初始值。这种详细的操作允许对MAXQ微控制器上的可用资源进行更严格的控制,但增加了系统的复杂性。
对于基于程序集的小型应用程序或不需要大量工作空间的应用程序,可以使用内部寄存器来存储所有应用程序变量。此方法具有两个重要优势:
紧凑、快速的代码。寄存器变量可以在短短一个指令周期内从另一个寄存器变量读取、写入或复制到另一个寄存器变量,具体取决于寄存器的位置。在基于MAXQ20的微控制器上,在最坏的情况下,通常不需要超过两个指令周期。
对变量的直接操作。一些内部寄存器位置可以直接操作。例如,可以选择 16 个工作累加器 A[0] 到 A[15] 中的任何一个(使用 AP 寄存器)作为活动累加器 Acc。这意味着,如果需要对存储在其中一个寄存器中的变量执行操作,则可以直接在该寄存器上执行该操作,而无需复制值、执行操作并重新复制值。类似地,存储在 LC[0] 和 LC[1] 寄存器中的变量可以通过执行 djnz 指令直接用作循环计数器。
较大的应用或需要大量工作变量的应用可以受益于将其部分或全部变量存储在基于SRAM的数据存储器中。此方法允许创建更多数量的变量,直至达到数据存储器大小的限制。以这种方式存储的变量可以使用MAXQ20内核的标准数据指针访问,该指针可用于读写字节大小或字大小的变量。(注:本应用笔记中的所有代码示例都假定DP[0]配置为在word模式下工作。
move DP[0], #0010h ; Location of variable in data memory move Acc, @DP[0] ; Read variable add #1 ; Increment variable value by 1 move @DP[0], Acc ; Store variable back in data memory
如果必须对变量执行一长串计算,则可以将该变量的值复制到工作寄存器中,如上面的示例代码所示。所有中间操作都可以使用该工作寄存器执行,并且一旦计算完成,该值就可以复制回变量。
MAX-IDE 中的段声明
一旦决定将应用变量存储在基于SRAM的数据存储器中,如何确定变量的存储位置?
通常,所有数据存储器都可供应用程序使用,但调试器使用的存储器中最高的 32 字节除外。这意味着声明变量只是在数据存储器中为其定义位置的问题。然后,每当读取或写入变量时,代码都会使用此位置。#define宏可用于将变量位置与符号名称相关联。
#define VarA #0020h #define VarB #0021h #define VarC #0022h move DP[0], VarA ; Point to VarA variable move Acc, @DP[0] ; Read value of variable move DP[0], VarB ; Point to VarB variable move @DP[0], Acc ; Copy VarA to VarB move DP[0], VarC ; Point to VarC variable move @DP[0], #1234h ; Set VarC = 1234h
这种方法效果很好,但它有几个问题。
每个变量的位置必须提前确定。此任务可能非常耗时,特别是如果以后决定将所有变量移动到数据存储器的不同区域。
必须注意不要意外地对多个变量使用相同的位置。如果犯了这个错误,可能很难跟踪错误。
变量的任何初始(起始)值都必须由应用程序代码显式加载,如上面最后一行所示。如果有许多变量要以这种方式初始化,则此操作可能会占用大量代码空间。
一种更有效的方法利用MAX-IDE的机制来声明单独的代码和数据段。此方法允许应用程序作者指定程序集代码文件的哪些部分发往代码空间,哪些部分发往数据空间。
segment code move DP[0], #VarA ; Point to VarA move Acc, @DP[0] ; Get current value of VarA add #1 ; Increment it move @DP[0], Acc ; Store value back in VarA segment data VarA: dw 0394h ; Initial value for VarA
在上述方法中,数据段中声明的变量的地址由汇编程序自动确定,因为它使用与代码空间中的标签分配地址相同的方法解析文件。标签用于为这些变量地址分配符号名称,dw 和 db 语句可用于初始化具有起始值的字大小和字节大小的变量。在这种情况下,假设在程序集文件中找不到以前的段数据指令,汇编程序将从地址 0000h 开始数据段。这意味着 VarA 将存储在字地址 0000h 处。与在代码空间中一样,org 语句可以强制变量位于指定地址的开头。
初始化数据段
在前面的代码清单中,变量 VarA 被定义为(使用 dw 语句)具有 0394h 的初始值。但此值永远不会加载到代码中的 VarA 中。那么,这个值是如何初始化的呢?答案是,数据段的初始化由MAX-IDE在项目编译和执行时自动执行。
MaxQAsm 汇编器通过生成辅助十六进制输出文件来响应段数据指令。通常,为包含代码数据的项目生成十六进制文件。例如,如果编译了项目“example.prj”,则将创建一个名为“example.hex”的十六进制文件,其中包含通过组装项目文件生成的代码数据。如果定义了数据段,则将创建一个名为“example_d.hex”的附加十六进制文件,其中包含在此段中组装的数据。
执行项目时,MAX-IDE 会检查在项目编译期间是否生成了数据段文件(以 _d.hex 结尾)。如果存在数据段文件,MAX-IDE使用标准JTAG加载器将来自该段的数据加载到器件的数据SRAM中。这是在将标准十六进制文件加载到程序内存后完成的。
这种方法在开发周期中效果很好,当器件连接到JTAG适配器并且MAX-IDE在每个应用程序运行之前重新加载代码和段数据时。但是,一旦器件断电和通电并允许独立运行(未连接调试器),MAX-IDE就无法再在每次运行前加载具有适当值的数据段。变量将不再设置为其预期值,因此应用程序可能无法正确执行。这种类型的故障可能很难分析,因为一旦器件重新连接到调试器,MAX-IDE将在每次运行之前再次开始加载数据段,问题将立即消失。
保存和恢复数据段
一个问题仍然存在:如何使应用程序始终如一地运行,无论是连接到调试器(每次运行前MAX-IDE重新加载代码和数据)还是自由运行(上电后RAM中没有特定内容保证)。显而易见的解决方案是一个两步过程:让应用程序将变量值(一旦初始化)保存在闪存中,并在每次复位或上电后恢复这些值。
第一步,应用程序必须将值保存到闪存。此操作在每个主擦除和代码加载周期之后首次执行应用程序时发生。
应用程序检查“标志”位置,以验证变量之前是否未复制到闪存。此标志可以是特殊用途的非变量位置,也可以与变量共享,只要该变量具有非零初始值(以将其与空白 RAM 位置区分开来)。
应用程序将每个变量值从数据RAM复制到闪存。在大多数带有可重写闪存的MAXQ微控制器(如MAXQ2000)上,这是使用UROM_flashWrite功能完成的。
应用程序在闪存中写入一个标志,以指示变量已存储。
作为第二步,在后续运行中,应用程序必须将变量值从闪存还原到数据RAM中的预期位置。
应用程序检查闪存中的标志位置,以验证变量值是否已存储。
应用程序使用 UROM_copyBuffer 例程将变量值从闪存复制到数据 RAM 中的适当位置。
下面的代码表演示了使用MAXQ2000评估板的保存-恢复方法。在此代码中,变量值存储在地址为 7000h–71FFh 的闪存中。
$include(maxQ2000.inc) ;; Code memory (flash) : 0000h-7FFFh (word addr) ;; Data memory (RAM) : 0000h-03FFh (word addr) org 0000h ljump start ; Skip over password area org 0020h start: move DPC, #1Ch ; Set all pointers to word mode move DP[0], #0F000h ; Check first variable value (flag) lcall UROM_moveDP0 ; 'move GR, @DP[0]' executed by Utility ROM move Acc, GR cmp #1234h jump NE, copyToFlash ;; This is the "free-running" code, executed on subsequent power-ups, that copies ;; values from the flash back into their proper data segment locations. move DP[0], #0F000h ; Source: Flash location 7000h move BP, #0 ; Dest: Start of RAM move Offs, #0 move LC[0], #100h ; Copy 256 words lcall UROM_copyBuffer jump main ;; This is the first-pass code. A bit of a trick here; because MAX-IDE enters ;; and exits the loader separately when loading the code and data segment files, ;; the application is allowed to execute briefly before the data segment file ;; has been loaded. The first four lines under copyFlash ensure that the ;; application waits for MAX-IDE to load the data segment file before continuing. copyToFlash: move DP[0], #0h ; Wait for flag variable to be loaded by MAX-IDE. move Acc, @DP[0] ; Note that this will reset the application; the cmp #1234h ; data segment is not loaded while the application jump NE, copyToFlash ; is still running. move DP[0], #0 ; Start of RAM variable area move A[4], #7000h ; Location in flash to write to move LC[0], #100h ; Store 256 words in flash 7000h-70FFh copyToFlash_loop: move DP[0], DP[0] ; Refresh the data pointer to read values correctly, ; because calling UROM_flashWrite changes memory ; contexts and affects the cached @DP[0] value move A[0], A[4] ; Location to write move A[1], @DP[0]++ ; Value to write (taken from RAM) lcall UROM_flashWrite move Acc, A[4] add #1 move A[4], Acc djnz LC[0], copyToFlash_loop main: move PD0, #0FFh ; Set all port 0 pins to output move PO0, #000h ; Drive all port 0 pins low (LEDs off) move DPC, #1Ch ; Set pointers to word mode move DP[0], #varA move Acc, @DP[0] cmp #1234h ; Verify that the variable is set correctly jump NE, fail pass: move PO0, #55h sjump $ fail: sjump $ segment data org 0000h varA: dw 1234h org 00FFh varB: dw 5678h end
结论
MAX-IDE提供的代码和数据段工具提供了一种在数据存储器中自动声明变量位置并使用起始值初始化这些变量的方法。然后,可以使用应用程序代码将这些变量值缓存在闪存中,并根据需要还原它们。这种方法允许基于汇编的应用利用MAX-IDE提供的数据段自动加载,同时无论微控制器是否连接到JTAG调试器,都能始终如一地运行。
审核编辑:郭婷
-
微控制器
+关注
关注
48文章
7891浏览量
153549 -
存储器
+关注
关注
38文章
7623浏览量
166156 -
JTAG
+关注
关注
6文章
403浏览量
72810
发布评论请先 登录
RT-Thread自动初始化详解

已初始化段的初始化数据在memoryCopy后初始化数据变了而且空间分配也没重叠
MAX-IDE入门
MAX-IDE Simulator User's G

MAX-IDE入门

ds1302时钟芯片初始化,自动决定DS1302是否需要初始化程序
在51平台下初始化文件的引入导致全局变量无法初始化的问题如何解决

霍尔无刷电机如何进行程序初始化?
RT-Thread自动初始化机制

MAX-IDE入门

将LCD仿真器与MAX-IDE和IAR嵌入式工作台开发环境配合使用


【H桥电机驱动电路原理】-学习笔记
工作原理电路分析这是一个由晶体管构成的H桥电机驱动电路,以下是对其各部分的介绍:核心器件晶体管:电路中使用了PNP型的SS8550(Q5、Q6)和NPN型的SS8050(Q9、Q10、Q13、Q14)。通过不同晶体管的导通与截止组合,实现电机两端电压极性的切换,进而控制电机正反转。比如,当Q5和Q10导通,Q6和Q9截止时,电流从MotorL+流入电机,从M

ATA-2041高压放大器在CFRP板分层缺陷的空耦超声原位测量中的应用
前言空气耦合超声波技术,作为一种高效且无损的检测方法,近年来在工业领域受到了广泛关注。其独特之处在于利用空气作为耦合介质,无需与被测物体直接接触,即可实现高精度的检测与成像。它能够检测在用CFRP板中的缺陷确保其应用安全,但传统的空气耦合超声方法通常依赖于线性缺陷指数在表征小尺寸缺陷方面无效。此外扫描步长完全限制了它们的成像空间分辨率,导致成像空间分辨率与检

TwinCAT3 EtherCAT抓包 | 技术集结
在使用TwinCAT测试EtherCATEOE功能时,我们会发现正常是无法使用Wireshark去进行网络抓包抓取EtherCAT报文的,今天这篇文章就带大家来上手EtherCAT抓包方式。准备环境硬件环境:EtherKit开发板网线一根Type-CUSB线一根软件环境TwinCAT3RT-ThreadstudiowiresharkEtherCATEOE工程

EtherCAT科普系列(8):EtherCAT技术在机器视觉领域的应用
机器视觉是基于软件与硬件的组合,通过光学装置和非接触式的传感器自动地接受一个真实物体的图像,并利用软件算法处理图像以获得所需信息或用于控制机器人运动的装置。机器视觉可以赋予机器人及自动化设备获取外界信息并认知处理的能力。机器视觉系统内包含光学成像系统,可以作为自动化设备的视觉器官实现信息的输入,并借助视觉控制器代替人脑实现信息的处理与输出。从而实现赋予自动化

新品 | 26+6TOPS强悍算力!飞凌嵌入式FCU3501嵌入式控制单元发布
飞凌嵌入式FCU3501嵌入式控制单元基于瑞芯微RK3588处理器开发设计,4xCortex-A76+4xCortex-A55架构,A76主频高达2.4GHz,A55核主频高达1.8GHz,支持8K编解码,NPU算力6TOPS,支持算力卡拓展,可以插装Hailo-8 26TOPS M.2算力卡。

接口核心板必选 | 视美泰AIoT-3568SC 、 AIoT-3576SC:小身材大能量,轻松应对多场景设备扩展需求!
在智能硬件领域,「适配」是绕不开的关键词。无论是小屏设备的”寸土寸金”,还是模具开发的巨额成本,亦或是多产品线兼容的复杂需求,开发者总在寻找一款能「以不变应万变」的核心解决方案。视美泰旗下的AIoT-3568SC与AIoT-3576SC接口核心板系列,可以说是专为高灵活适配场景而生!无需为设备尺寸、模具限制或产品线差异妥协,一块核心板,即可释放无限可能。为什

3核A7+单核M0多核异构,米尔全新低功耗RK3506核心板发布
近日,米尔电子发布MYC-YR3506核心板和开发板,基于国产新一代入门级工业处理器瑞芯微RK3506,这款芯片采用三核Cortex-A7+单核Cortex-M0多核异构设计,不仅拥有丰富的工业接口、低功耗设计,还具备低延时和高实时性的特点。核心板提供RK3506B/RK3506J、商业级/工业级、512MB/256MBLPDDR3L、8GBeMMC/256

搭建树莓派网络监控系统:顶级工具与技术终极指南!
树莓派网络监控系统是一种经济高效且功能多样的解决方案,可用于监控网络性能、流量及整体运行状况。借助树莓派,我们可以搭建一个网络监控系统,实时洞察网络活动,从而帮助识别问题、优化性能并确保网络安全。安装树莓派网络监控系统有诸多益处。树莓派具备以太网接口,还内置了Wi-Fi功能,拥有足够的计算能力和内存,能够在Linux或Windows系统上运行。因此,那些为L

STM32驱动SD NAND(贴片式SD卡)全测试:GSR手环生物数据存储的擦写寿命与速度实测
在智能皮电手环及数据存储技术不断迭代的当下,主控 MCU STM32H750 与存储 SD NAND MKDV4GIL-AST 的强强联合,正引领行业进入全新发展阶段。二者凭借低功耗、高速读写与卓越稳定性的深度融合,以及高容量低成本的突出优势,成为大规模生产场景下极具竞争力的数据存储解决方案。

芯对话 | CBM16AD125Q这款ADC如何让我的性能翻倍?
综述在当今数字化时代,模数转换器(ADC)作为连接模拟世界与数字系统的关键桥梁,其技术发展对众多行业有着深远影响。从通信领域追求更高的数据传输速率与质量,到医疗影像领域渴望更精准的疾病诊断,再到工业控制领域需要适应复杂恶劣环境的稳定信号处理,ADC的性能提升成为推动这些行业进步的重要因素。行业现状分析在通信行业,5G乃至未来6G的发展,对基站信号处理提出了极

史上最全面解析:开关电源各功能电路
01开关电源的电路组成开关电源的主要电路是由输入电磁干扰滤波器(EMI)、整流滤波电路、功率变换电路、PWM控制器电路、输出整流滤波电路组成。辅助电路有输入过欠压保护电路、输出过欠压保护电路、输出过流保护电路、输出短路保护电路等。开关电源的电路组成方框图如下:02输入电路的原理及常见电路1AC输入整流滤波电路原理①防雷电路:当有雷击,产生高压经电网导入电源时

有几种电平转换电路,适用于不同的场景
一.起因一般在消费电路的元器件之间,不同的器件IO的电压是不同的,常规的有5V,3.3V,1.8V等。当器件的IO电压一样的时候,比如都是5V,都是3.3V,那么其之间可以直接通讯,比如拉中断,I2Cdata/clk脚双方直接通讯等。当器件的IO电压不一样的时候,就需要进行电平转换,不然无法实现高低电平的变化。二.电平转换电路常见的有几种电平转换电路,适用于

瑞萨RA8系列教程 | 基于 RASC 生成 Keil 工程
对于不习惯用 e2 studio 进行开发的同学,可以借助 RASC 生成 Keil 工程,然后在 Keil 环境下愉快的完成开发任务。

共赴之约 | 第二十七届中国北京国际科技产业博览会圆满落幕
作为第二十七届北京科博会的参展方,芯佰微有幸与800余家全球科技同仁共赴「科技引领创享未来」之约!文章来源:北京贸促5月11日下午,第二十七届中国北京国际科技产业博览会圆满落幕。本届北京科博会主题为“科技引领创享未来”,由北京市人民政府主办,北京市贸促会,北京市科委、中关村管委会,北京市经济和信息化局,北京市知识产权局和北辰集团共同承办。5万平方米的展览云集

道生物联与巍泰技术联合发布 RTK 无线定位系统:TurMass™ 技术与厘米级高精度定位的深度融合
道生物联与巍泰技术联合推出全新一代 RTK 无线定位系统——WTS-100(V3.0 RTK)。该系统以巍泰技术自主研发的 RTK(实时动态载波相位差分)高精度定位技术为核心,深度融合道生物联国产新兴窄带高并发 TurMass™ 无线通信技术,为室外大规模定位场景提供厘米级高精度、广覆盖、高并发、低功耗、低成本的一站式解决方案,助力行业智能化升级。
评论