指向16位控制器上的寄存器的指针

1 embedded pointers iar rl78

如何使用IAR的EWB RL78编译器将16位瑞萨RL78微控制器上的指针声明到具有20位地址的寄存器?

例如:

static int *ptr = (int *)0xF1000;
Run Code Online (Sandbox Code Playgroud)

上述方法不起作用,因为指针是16位地址.

Cli*_*ord 5

如果有问题的寄存器是片上外设,那么很可能是你的工具链已经包含已宣告所有的寄存器,在这种情况下,你应该使用一个处理器头.如果由于某种原因你不能或不希望这样做,那么你至少可以看看它是如何声明这样的寄存器的.

在任何情况下,你至少应该申报的地址volatile,因为它不是一个普通的内存位置,可能无法控制和代码的知识改变为正常周边行为的一部分.此外,您应该使用显式大小的数据类型,并且该寄存器不太可能被签名.

#include <stdint.h>

...

static volatile uint16_t* ptr = (uint16_t*)0xF1000u ;
Run Code Online (Sandbox Code Playgroud)

添加了以下对目标体系结构的说明:

IAR RL78编译器支持两种数据模型 - 近端远端.从IAR编译器手册:

●Near数据模型可以访问最高64 KB数据存储器中的数据

●远程数据模型可以处理整个1 MB数据存储器中的数据.

近模型是默认模型.远模型可以使用编译器选项进行设置:--data_model=far; 这将全局更改指针类型以允许20位寻址(在这种情况下指针长度为3个字节).

即使没有全局指定数据模型,也可以通过使用关键字__near和显式指定指针类型来覆盖默认指针类型__far.所以在问题的例子中,正确的声明是:

static volatile uint16_t __far* ptr = (uint16_t*)0xF1000u ;
Run Code Online (Sandbox Code Playgroud)

请注意,__far关键字的位置至关重要.它的位置可以用来声明指针远存储器,或指针远存储器(或者你甚至可以同时声明并在远存储器).

在RL78上,0xF1000实际上是指数据闪存的开始,而不是问题中所述的寄存器.通常,指向寄存器的指针不会被更改(这意味着它指的是不同的寄存器),因此可能合理地声明为const:

static volatile uint16_t __far* const ptr = (uint16_t*)0xF1000u ;
Run Code Online (Sandbox Code Playgroud)

类似于__far位置对const语义至关重要.以上内容防止ptr被修改但允许ptr修改的内容.作为闪存,这可能并不总是令人满意或可能的,因此可以合理地将其声明为指向const值的const指针.

请注意,对于RL78特殊功能寄存器(SFR),IAR编译器有一个__sfr专门用于寻址区域0xFFF00-0xFFFFF中的寄存器的关键字:

例:

#pragma location=0xFFF20
__no_init volatile uint8_t __sfr PORT1;  // PORT1 is located at address 0xFFF20
Run Code Online (Sandbox Code Playgroud)

使用IAR specfic编译器扩展的替代语法:

__no_init volatile uint8_t __sfr PORT1 @ 0xFFF20 ;
Run Code Online (Sandbox Code Playgroud)