当前位置:首页 > 嵌入式 > 嵌入式硬件


在MAX-IDE中自动初始化数据段

摘要:该应用笔记讨论了MAX-IDE提供的程序和数据段的灵活工具,用于MAXQ®微控制器的应用编程。程序和数据段机制能够在数据存储器自动声明变量位置,并以起始值对这些变量进行初始化。应用程序可以将这些变量值缓存在闪存内,并在需要时恢复这些数据。该方法允许基于汇编语言的应用程序充分利用MAX-IDE提供的数据段自动装载功能,无论微控制器与JTAG调试器是否连接都能保持工作。MAXQ2000微控制器评估板能够演示这一方案,本文给出了相应的例程。

概述MAXQ汇编程序的变量可以存储在工作寄存器(例如累加器A[0]至A[15])或数据存储器(SRAM)。在数据存储器中存储变量能够为应用程序变量提供较大的工作区域,但需要额外的访问时间。

MaxQAsm编译器和MAX-IDE环境提供单独声明程序段和数据段的机制,对各段产生各自的hex输出文件。运行时,MAX-IDE自动将程序段文件装载到程序存储器(通常为闪存),将数据段文件装载到数据存储器(通常为RAM)。然而,由于数据存储器为易失存储器,一旦微控制器掉电,将丢失数据段内容。

本文利用MAXQ2000 EV (评估)板首先演示应用程序开始运行时如何将预装载数据存储器值保存到闪存内,随后演示微控制器重新上电时如何从闪存刷新数据段。无论应用程序处于开发阶段(连接到JTAG适配器和MAX-IDE)还是在现场运行,这两个步骤都允许使用相同的数据段机制声明和初始化变量。

该应用笔记的例程为MAXQ2000微控制器以及MAXQ2000评估板编写,但相应程序和原理适用于任何基于MAXQ20、能够重新编程闪存的微控制器。

提供最新版本的安装软件和关于MAX-IDE环境的文档,可免费下载。 MAX-IDE安装程序 MAXQ核编译指南 开发工具指南 变量和存储位置嵌入式应用通常需要一定的工作区域存储状态信息、配置数据、中间数据、循环计数器以及计算结果。存储在该工作区域的数据通常作为变量,具有以下特征。 它们是临时数据。如果应用程序由于电源失效或复位产生中断,不需要保存这些数据。 它们可频繁访问和更新。它们必须存储在能够快速读写的位置;这些位置的写入次数必须没有限制。 它们具有定义的初始值。程序开始运行时,用户程序必须将它们设置为特定值。 用C语言或其它高级语言编写的程序编译成汇编代码,编译器通常自动为变量分配空间(同时将变量初始化为预先定义的起始值)。这种情况下,用户只需声明变量、变量类型及其初始值(可选),其余工作由编译器处理。

unsigned int c = 0x1234; 然而,用MAXQ汇编语言编写应用程序时,必须明确指定变量分配空间并设置变量初始值。这些细节能够严格控制MAXQ微控制器的资源,但增加了系统复杂性。

对于基于汇编的小型应用程序或不需要大量工作区域的应用程序,内部寄存器可用来存储所有应用程序变量。这种方法具有两个重要优势: 程序结构紧凑、运行速度快。根据寄存器位置,在一个指令周期内可实现寄存器变量的读取、写入或复制其它寄存器变量。对基于MAXQ20的微控制器,在最差工作条件下,通常最多占用不超过两个指令周期。 直接操作变量。可直接操作一些内部寄存器。例如,可以(使用AP寄存器)选择16个工作累加器A[0]至A[15]的任何一个作为有效累加器Acc。这就意味着如果需要对这些寄存器存储的一个变量进行操作时,可直接对寄存器进行操作,无需将数据复制出来进行操作后再将数据复制回去。同样,执行djnz指令时,存储在LC[0]和LC[1]寄存器的变量可直接作为循环计数器。 对于大规模应用程序或者当应用程序需要大量工作变量时,可将其中一些或所有变量存储在基于SRAM的数据存储器。这种方式允许创建更多的变量,具体受限于数据存储器的空间。按照这种方式存储的变量可以通过MAXQ20核的标准数据指针访问,该指针用于读取或写入字节宽度或字宽变量(注意:本应用笔记的例程假定DP[0]配置为工作在字模式)。

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 VarAsegment dataVarA: dw 0394h ; Initial value for VarA利用上述方案,在数据段声明的变量地址由编译器解析文件时自动指定,用同样方法为程序空间分配地址标签。标签用于对变量地址指定符号名称,dw和db声明可以在初始化变量时用于设置字宽或字节宽度初始值。这种情况下,假定汇编文件中事先没有segment data指令,编译器将从0000h地址起始数据段。这意味着VarA将存储在字地址0000h。对于程序空间,org声明将强制变量从指定的起始地址开始存储。

数据段初始化在先前的程序清单中,变量VarA定义(用dw声明)的初始值为0394h。但是,该值在程序中并不装载到VarA。那么,如何初始化这一数值? 答案是在编译和运行工程时,MAX-IDE将自动执行数据段初始化。

MaxQAsm编译器通过产生一个二级hex输出文件响应segment data指令。通常,为工程产生的hex文件包含程序数据。例如,如果编译工程"example.prj",将产生一个名称为"example.hex"的hex文件,并包含通过编译工程文件产生的程序数据。如果定义了数据段,则将产生一个名称为"example_d.hex"的附加hex文件,该文件包含该段编译数据。

执行工程时,MAX-IDE检查是否在工程编译中产生了数据段文件(以_d.hex结尾)。如果存在数据段文件,MAX-IDE通过标准的JTAG装载器将该段数据装载到器件的数据SRAM。该过程在标准的hex文件装载到程序存储器之后执行。

这种方案能够很好地工作在开发阶段,当器件连接到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 areaorg 0020hstart: 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-70FFhcopyToFlash_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_loopmain: 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, failpass: move PO0, #55h sjump $fail: sjump $segment dataorg 0000hvarA: dw 1234horg 00FFhvarB: dw 5678hend结论MAX-IDE提供的程序段和数据段工具能够在数据存储器中自动声明变量地址,以起始值初始化这些变量。可以利用应用程序在闪存中缓存这些变量,必要时恢复它们。这种方法允许基于汇编的应用程序使用MAX-IDE提供的数据段自动装载功能,无论微控制器是否连接JTAG调试器,都能保持工作。

本站声明: 本文章由作者或相关机构授权发布,目的在于传递更多信息,并不代表本站赞同其观点,本站亦不保证或承诺内容真实性等。需要转载请联系该专栏作者,如若文章内容侵犯您的权益,请及时联系本站删除。
换一批
延伸阅读

全新的专有模型导入功能让客户更轻松地将其专属模型导入到Amazon Bedrock中,从而充分利用Amazon Bedrock的强大功能。全新的模型评估功能使客户能够广泛且便捷地选择完全托管模型,包括RAG优化的新版Am...

关键字: 生成式AI 基础模型 数据

2024年4月17日,中国 – 服务多重电子应用领域、全球排名前列的半导体公司意法半导体(STMicroelectronics,简称ST;纽约证券交易所代码:STM)将在2024年4月25日欧洲证券交易所开盘前公布202...

关键字: 半导体 数据

数据占满我们的电子设备已成常态,为了满足广大用户的需求,NAS应运而生。然而,对于许多普通用户来说,NAS设备的设置和使用却常常令人望而却步。不过,铁威马TOS 6的出现,不仅功能强大,而且操作简便,即使是初次接触NAS...

关键字: 数据 电子设备 NAS

机器学习作为人工智能领域的重要组成部分,其过程涉及到多个核心环节。本文将详细阐述机器学习的四个主要步骤:数据准备、模型选择、模型训练与评估,以及模型部署与应用,以揭示机器学习从数据到应用的完整流程。

关键字: 数据 人工智能 机器学习

机器学习算法是人工智能领域中的核心技术之一,它通过对大量数据进行学习,自动发现数据中的规律和模式,从而实现对新数据的预测、分类、聚类等任务。本文将深入探讨机器学习算法的基本过程,包括数据准备、模型选择、训练与评估等关键步...

关键字: 数据 人工智能 机器学习

在嵌入式系统开发、调试和测试过程中,J-Link作为一种高效的调试工具,为开发者提供了极大的便利。然而,要想充分发挥J-Link的功能,首先需要正确安装其驱动程序。本文将详细介绍J-Link驱动的安装过程,并深入解析其中...

关键字: jlink 嵌入式系统 嵌入式开发

与谷歌的合作使 Nordic 能够在 nRF Connect SDK 中嵌入开发人员软件,以构建与安卓移动设备兼容的谷歌Find My Device和未知跟踪器警报服务

关键字: 谷歌 SoC 嵌入式开发

嵌入式开发作为当今电子工程和信息技术领域的核心分支,涵盖了广泛的软硬件技术和系统集成方法,用于构建高性能、低成本、低功耗、体积小巧且功能专一的嵌入式系统。这些系统无处不在,从微型传感器节点到复杂的工业控制设备,从日常使用...

关键字: 嵌入式开发 Python

嵌入式开发是当今信息技术领域不可或缺的一部分,它融合了硬件设计、软件开发和系统集成等多个学科,专门用于创建那些被嵌入到特定设备或系统中的专用计算机系统。嵌入式开发的主要过程包括利用分立元件或集成器件进行电路设计、结构设计...

关键字: 嵌入式开发 硬件设计 软件开发

嵌入式开发作为一种专业且技术密集型的领域,涵盖了从硬件底层驱动、中间件到应用层软件开发等多个层面的工作,其所需的工具种类繁多,各有针对性,旨在提升开发效率、保证代码质量以及简化调试过程。

关键字: 嵌入式开发 keil
关闭
关闭