存储在程序存储器中的数据不能直接在MAXQ®微控制器上访问。相反,IAR 嵌入式工作台®用于调用 C 代码中的特殊函数,这些功能在微控制器的 ROM 中为此任务提供。本应用笔记解释了从应用代码调用ROM所需的步骤。
概述
程序员在使用微控制器时,通常在应用程序代码中使用查找表。然而,由于MAXQ内核的性质,应用软件不能直接从代码空间读取,因此不能直接访问应用代码中定义的任何表。为了缓解这个问题,所有MAXQ微控制器都实现了所谓的“伪冯诺依曼”架构:开发人员可以在程序空间中存储数据和表,但只能使用特殊的实用程序ROM例程。除了这些核心功能外,每个MAXQ微控制器的ROM都可以具有特定于该器件的例程。本应用笔记描述了使用IAR嵌入式工作台从代码访问这些实用程序ROM功能时必须采取的步骤。
指定函数地址和原型
使用 ROM 功能的第一步是确定这些功能的位置。MAXQ器件用户指南补充列出了实用程序ROM用户功能、地址、输入和输出。使用此信息查找要调用的函数的入口点。例如,下面的表1(MAXQ48补充的表2000)显示flashWrite功能位于字地址08461h。
表 1.实用程序 ROM 用户功能(适用于实用程序 ROM 版本 1.01)
功能编号 | 函数名称 | 入口点 | 总结 |
0 | 闪写 | 08461h | 对单个字的闪存进行编程。 |
1 | 闪光擦除页面 | 08467h | 擦除(FFFFh 的程序)一个 256 字的闪存扇区。 |
2 | frashEraseAll | 08478h | 擦除(程序到 FFFFh)所有闪存。 |
3 | 移动DP0 | 08487h | 在 DP[0] 处读取一个字节/字 |
4 | 移动DP0inc | 0848安 | 在 DP[0] 处读取一个字节/字,然后递增 DP[0]。 |
5 | 移动DP0dec | 0848分 | 读取 DP[0] 处的字节/字,然后递减 DP[0]。 |
6 | 移动DP1 | 08490h | 在 DP[1] 处读取一个字节/字。 |
7 | 移动DP1inc | 08493h | 在 DP[1] 处读取一个字节/字,然后递增 DP[0]。 |
8 | 移动DP1dec | 08496h | 读取 DP[1] 处的字节/字,然后递减 DP[0]。 |
9 | 移动FB | 08499h | 读取 BP[关闭] 处的字节/字。 |
10 | 移动FPinc | 0849通道 | 读取 BP[Offs] 处的字节/字,然后递增 Offs。 |
11 | 移动FPdec | 0849Fh | 读取 BP[Offs] 处的字节/字,然后递减 Offs。 |
12 | 复制缓冲区 | 084A2h | 将 LC[0] 值从 DP[0] 复制到 BP[关闭]。 |
现在,各种功能的入口点已经知道,IAR嵌入式工作台可以配置为使用这些地址。从“项目”菜单中选择“选项”。在出现的对话框中,从“类别”列表中选择“链接器”。单击“额外选项”选项卡,并确保选中标有“使用命令行选项”的框。在选项列表中,您必须为要使用的每个实用程序ROM功能添加一个项目;指定该函数的地址。这些选项应具有以下格式: 《function_name》是将从应用程序代码调用的函数名称。它不必与上表中给出的名称匹配,但它必须是有效的 C 代码函数名称。《hexadecimal_byte_address》是 ROM 函数入口点的字节地址。由于该表列出了单词地址,因此您需要将它们乘以 1 才能将它们转换为字节地址。下面是一个MAXQ2000项目选项示例(图《》),该项目使用三个ROM功能。
-D=
图1.MAXQ2000项目示例使用三个ROM功能。
若要使这些函数可通过应用程序代码访问,请使用在“选项”屏幕中指定的相同名称为每个函数声明原型。参数传递将在下一节中讨论,因此现在声明每个原型不接受任何参数且没有返回值。
extern void utilFlashWrite(void); extern void utilFlashErasePage(void); extern void utilMoveDP0(void);
创建包装函数
现在可以直接从应用程序代码调用 ROM 函数。但是,有一个警告。由于函数通常在与IAR编译器使用的寄存器不同的寄存器中接受其输入参数,因此这些函数可能会破坏编译器所依赖的寄存器。这些函数可能还需要在禁用中断的情况下执行。因此,您应该创建一些帮助程序函数来处理这些问题。对于要调用的每个 ROM 函数,确定:它接受哪些输入;它提供的输出;以及它销毁的寄存器。所有这些信息都可以在MAXQ器件的用户指南补充中找到。
继续上面的例子,可以看到MAXQ2000的flashErasePage函数有如下说明:
功能:闪存擦除页面
摘要:擦除(程序到0FFFFh)265字的闪存页。
输入:A[0]:位于要擦除的页面中的单词地址。(页码是 A[0] 的高字节。
输出:进位:错误时设置,成功时清除。
摧毁:PSF,LC[1],GR,AP,AP,APC
笔记:
如果看门狗复位功能处于活动状态,则应在调用此函数之前将其禁用。
从 flash 调用此函数时,应注意返回地址不在要擦除的页面中。
使用此信息,您可以创建一个调用 flashErasePage 的帮助程序函数。除了实际调用实用程序 ROM 函数外,此帮助程序函数还需要执行四个附加步骤:
配置 ROM 功能的输入。
保存并恢复 ROM 功能销毁的任何保留寄存器。
处理 ROM 函数的输出。
保存、禁用和恢复调用 ROM 函数周围的中断。
准备输入
此示例 ROM 函数接受 A[0] 作为其输入,设置 A[0] 非常简单。我们可以通过使用一些IAR关键字和宏为MAXQ中的任何寄存器声明一个变量。要为 A[0] 声明变量,请添加以下语句:
__no_init volatile __io unsigned int A0 @ _M(0x09,0x00);
特别注意_M宏的数据类型和输入。此变量 A0 被声明为“无符号 int”,因为它是一个 16 位寄存器。如果它是一个 8 位寄存器,我们可以将其声明为“无符号字符”。_M宏的输入是模块编号,后跟A[0]寄存器的偏移。现在,您只需将此变量设置为 A[0] 中所需的值即可。
A0 = pageAddr;
保存特殊登记册
以上述方式使用寄存器时必须小心,因为编译器希望某些寄存器不会从一个函数调用更改为下一个函数调用。MAXQ IAR C编译器参考指南列出了以下寄存器(表2)作为暂存器。您可以在不干扰程序流的情况下销毁这些寄存器。此外,APC 和 DP[1] 寄存器以及 DPC 寄存器的位 0、1 和 3 在任何时候都不应修改。如果函数更改了任何其他寄存器,则应在退出该函数之前恢复它们。
表 2.暂存寄存器1
MAXQ10器件 | MAXQ20器件 |
A[0], A[1], A[2], A[3], GR, LC[0], LC[1], DP[0], BP, OFFS, AP |
A[0], A[1], A[2], A[3], A[4], A[5], A[6], A[7], GR,LC[0], LC[1], DP[0]。英国石油公司,关闭,美联社 |
flashErasePage 描述将 APC 列为已销毁的寄存器之一,因此您必须确保在调用 utilFlashErasePage 之前保存并恢复该寄存器。如果您使用 IAR 的 asm() 函数,此任务也很简单。MAXQ汇编语句可以使用这个函数直接插入到C代码中。由于需要保存 APC,因此只需在调用 utilFlashErasePage 时添加 asm(“push APC”) 和 asm(“pop APC”) 语句即可。
处理 ROM 函数的输出
处理 ROM 函数的返回类似于处理输入。您可以直接读取相应的寄存器。例如,flashErasePage函数设置错误的进位。您可以使用 IAR 提供的 iomaxq.h 头文件中声明的PSF_bit结构直接访问此位。
return (PSF_bit.C == 0);
保存、禁用和恢复中断
要考虑的最后一个任务是是否需要禁用中断。大多数实用程序ROM例程都假定它们不会被中断。因此,如果您的应用程序使用中断,明智的做法是在调用实用程序 ROM 函数之前禁用它们。禁用它们的最简单方法是使用 iomaxq.h 头文件中定义的IC_bit结构和 intrinsics.h 文件中定义的 __disable_interrupt() 函数。
unsigned char origIGE = IC_bit.IGE; // Save current state. __disable_interrupt(); /* Add UROM call code here. */ IC_bit.IGE = origIGE; // Restore interrupt state.如果执行所有这些步骤,您将获得类似于以下内容的代码:
#include#include // Prototype for the real Utility ROM function. extern void utilFlashErasePage(void); // Define the register we need direct access to. __no_init volatile __io unsigned int A0 @ _M(0x09,0x00); unsigned char flashErasePage(unsigned int page) { unsigned int pageAddr; unsigned char origIGE; pageAddr = page << 8; // Change page # to an address. origIGE = IC_bit.IGE; // Save current state. __disable_interrupt(); A0 = pageAddr; // Set up input to UROM function. asm("push APC"); // UROM function destroys APC. utilFlashErasePage(); // Call actual UROM function. asm("pop APC"); // Restore APC. IC_bit.IGE = origIGE; // Restore interrupt state. return (PSF_bit.C == 0); // Check return code from UROM. }
结论
使用上述步骤,您可以轻松调用每个MAXQ微控制器的实用程序ROM中提供的功能。您可以创建函数包装器,利用MAXQ实用程序ROM中的代码访问查找表,在程序空间中存储数据,以及MAXQ系列器件独有的其他功能。
审核编辑:郭婷
全部0条评论
快来发表一下你的评论吧 !