如何使用IAR的EWB RL78编译器将16位Renesas RL78微控制器上的指针声明到具有20位地址的寄存器?
例如:
static int *ptr = (int *)0xF1000;
上述方法不起作用,因为指针是16位地址。
答案 0 :(得分:5)
如果有问题的寄存器是片上外设,那么很可能你的工具链已经包含一个声明了所有寄存器的处理器头,在这种情况下你应该使用它。如果由于某种原因你不能或不希望这样做,那么你至少可以看看它是如何声明这样的寄存器。
在任何情况下,您至少应声明地址volatile
,因为它不是常规内存位置,并且可能会更改超出代码的控制和知识,作为正常外设行为的一部分。此外,您应该使用显式大小的数据类型,并且此寄存器不太可能已签名。
#include <stdint.h>
...
static volatile uint16_t* ptr = (uint16_t*)0xF1000u ;
添加以下目标架构说明:
IAR RL78编译器支持两种数据模型 - near 和 far 。从IAR编译器手册:
●Near数据模型可以访问最高64 KB数据的数据 记忆
●远数据模型可以处理整个1 MB的数据 数据记忆。
近模型是默认模型。可以使用编译器选项设置far模型:--data_model=far
;这将全局更改指针类型以允许20位寻址(在这种情况下指针长度为3个字节)。
即使没有全局指定数据模型,也可以通过使用关键字__near
和__far
显式指定指针类型来覆盖默认指针类型。所以在问题的例子中,正确的声明是:
static volatile uint16_t __far* ptr = (uint16_t*)0xF1000u ;
请注意__far
关键字的位置至关重要。它的位置可用于声明一个指针到远存储器,或远存储器中的指针(或者你甚至可以在远存储器中声明它们。)
在RL78上,0xF1000实际上是指数据闪存的开始,而不是问题中所述的寄存器。通常,指向寄存器的指针不会被更改(这意味着它指的是不同的寄存器),因此可能合理地声明为const:
static volatile uint16_t __far* const ptr = (uint16_t*)0xF1000u ;
与__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
使用IAR specfic编译器扩展的替代语法:
__no_init volatile uint8_t __sfr PORT1 @ 0xFFF20 ;