Arm 如何在Ada中生成常量函数?

Arm 如何在Ada中生成常量函数?,arm,ada,Arm,Ada,我正在研制一种有钻头带的手臂系统。这涉及到计算地址和定义要计算地址的对象。我想定义一个函数来计算这些地址,但我真的找不到语言的方法。我能想到的最好的方法是一个通用包,其中的参数被输入到计算中。其中一个问题是,我必须(也许你可以纠正我,我是初学者)在两个独立的语句中使用它,一个用于定义实例化包,另一个用于使用它。那么有没有一种不那么复杂的方法呢?你也可以少说些废话吗?我觉得我在用不必要的污点弄脏我的文件 以下是我到目前为止的收获: generic register_base : Natur

我正在研制一种有钻头带的手臂系统。这涉及到计算地址和定义要计算地址的对象。我想定义一个函数来计算这些地址,但我真的找不到语言的方法。我能想到的最好的方法是一个通用包,其中的参数被输入到计算中。其中一个问题是,我必须(也许你可以纠正我,我是初学者)在两个独立的语句中使用它,一个用于定义实例化包,另一个用于使用它。那么有没有一种不那么复杂的方法呢?你也可以少说些废话吗?我觉得我在用不必要的污点弄脏我的文件

以下是我到目前为止的收获:

generic
    register_base : Natural;
    bit_number : Natural;
package PeriphBitBand is
    address: constant System.Address := System'To_Address(Peripheral_Alias_Base+ (register_base - Peripheral_Base)*32 + bit_number*4);
end PeriphBitBand;
还有一个用法:

generic
    RCC_ENABLE_REGISTER_Base : Natural;
    RCCBit : Natural;
package STM32F4.GenericPeripheral is
    RCC_ENABLE   : Boolean with Atomic, size=>32;
private
    package add is new PeriphBitBand(RCC_ENABLE_REGISTER_Base, RCCBit);
    for RCC_ENABLE'Address use add.address;
end STM32F4.GenericPeripheral;

从您所在的位置开始,最简单的方法可能是函数:

with Whatever_Declares_Addresses;

function reg_bit_to_address (register_base,bit_number : Natural) 
   return System.Address is
begin
   return System'To_Address (Whatever_Declares_Addresses.Peripheral_Alias_Base + 
                            (register_base - Peripheral_Base) * 32 + 
                             bit_number * 4);
end reg_bit_to_address;
...
RCC_ENABLE   : Boolean with Atomic, size=>32;
for RCC_ENABLE'Address use reg_bit_to_address (RCC_ENABLE_REGISTER_Base, RCCBit);
由于函数调用是在声明RCC_Enable时(紧接着)计算的,因此其结果是常量,至少在RCC_Enable超出范围之前是如此

但是,最好将
RCC\u Enable\u Register
声明为记录,其中一个组件是名为
RCC\u Enable
的布尔值,或者简单地称为
Enable
,因为它可以被称为
RCC\u Enable\u Register.Enable。有标准语法用于定义记录中每个组件的地址、布局和大小

由于诸如
RCC\u Enable\u Register.Enable之类的限定表达式可能会变得冗长,因此可以使用“重命名”来简化它们,例如


它为当前作用域的持续时间声明了一个速记形式。因为它只是一个重命名,所以没有执行惩罚,当然,如果您将它保留在使用它的地方,您不必搜索很远就可以找到它的定义…

从您所在的位置开始,最简单的方法可能是函数:

with Whatever_Declares_Addresses;

function reg_bit_to_address (register_base,bit_number : Natural) 
   return System.Address is
begin
   return System'To_Address (Whatever_Declares_Addresses.Peripheral_Alias_Base + 
                            (register_base - Peripheral_Base) * 32 + 
                             bit_number * 4);
end reg_bit_to_address;
...
RCC_ENABLE   : Boolean with Atomic, size=>32;
for RCC_ENABLE'Address use reg_bit_to_address (RCC_ENABLE_REGISTER_Base, RCCBit);
由于函数调用是在声明RCC_Enable时(紧接着)计算的,因此其结果是常量,至少在RCC_Enable超出范围之前是如此

但是,最好将
RCC\u Enable\u Register
声明为记录,其中一个组件是名为
RCC\u Enable
的布尔值,或者简单地称为
Enable
,因为它可以被称为
RCC\u Enable\u Register.Enable。有标准语法用于定义记录中每个组件的地址、布局和大小

由于诸如
RCC\u Enable\u Register.Enable之类的限定表达式可能会变得冗长,因此可以使用“重命名”来简化它们,例如


它为当前作用域的持续时间声明了一个速记形式。因为它只是一个重命名,没有执行惩罚,当然,如果你把它放在你使用它的地方,你不必搜索太远就可以找到它的定义…

为了好玩,我试着按照@BrianDrummond的想法将我找到的破损代码翻译成Ada

C代码是

#include <stdio.h>

#define BITBAND_SRAM_REF 0x20000000
#define BITBAND_SRAM_BASE 0x22000000
// Convert SRAM address
#define BITBAND_SRAM(a,b) \
  ((BITBAND_SRAM_BASE + (a-BITBAND_SRAM_REF)*32 + (b*4)))

#define BITBAND_PERI_REF 0x40000000
#define BITBAND_PERI_BASE 0x42000000
// Convert PERI address
#define BITBAND_PERI(a,b) \
  ((BITBAND_PERI_BASE + (a-BITBAND_PERI_REF)*32 + (b*4)))

#define MAILBOX 0x20004000
#define TIMER 0x40004000
// Mailbox bit 0
#define MBX_B0 *((volatile unsigned int *)(BITBAND_SRAM(MAILBOX,0)))
// Mailbox bit 7
#define MBX_B7 *((volatile unsigned int *)(BITBAND_SRAM(MAILBOX,7)))
// Timer bit 0
#define TIMER_B0 *((volatile unsigned char *)(BITBAND_PERI(TIMER,0)))
// Timer bit 7
#define TIMER_B7 *((volatile unsigned char *)(BITBAND_PERI(TIMER,7)))

int main(void){
    printf("%x\n", &MBX_B0);
    return 0;
}
连同测试

with Ada.Text_IO;
with Bitbanding;
with System.Storage_Elements;
procedure Bitbanding_Test is
   package Address_IO
     is new Ada.Text_IO.Modular_IO (System.Storage_Elements.Integer_Address);
begin
   Address_IO.Put
     (System.Storage_Elements.To_Integer (Bitbanding.MBX_B0'Address),
      Base => 16);
   Ada.Text_IO.New_Line;
end Bitbanding_Test;

它给出了与C相同的数值结果(
16#22080000#
)。

为了好玩,我试着按照@BrianDrummond的想法将我找到的被破坏的代码翻译成Ada

C代码是

#include <stdio.h>

#define BITBAND_SRAM_REF 0x20000000
#define BITBAND_SRAM_BASE 0x22000000
// Convert SRAM address
#define BITBAND_SRAM(a,b) \
  ((BITBAND_SRAM_BASE + (a-BITBAND_SRAM_REF)*32 + (b*4)))

#define BITBAND_PERI_REF 0x40000000
#define BITBAND_PERI_BASE 0x42000000
// Convert PERI address
#define BITBAND_PERI(a,b) \
  ((BITBAND_PERI_BASE + (a-BITBAND_PERI_REF)*32 + (b*4)))

#define MAILBOX 0x20004000
#define TIMER 0x40004000
// Mailbox bit 0
#define MBX_B0 *((volatile unsigned int *)(BITBAND_SRAM(MAILBOX,0)))
// Mailbox bit 7
#define MBX_B7 *((volatile unsigned int *)(BITBAND_SRAM(MAILBOX,7)))
// Timer bit 0
#define TIMER_B0 *((volatile unsigned char *)(BITBAND_PERI(TIMER,0)))
// Timer bit 7
#define TIMER_B7 *((volatile unsigned char *)(BITBAND_PERI(TIMER,7)))

int main(void){
    printf("%x\n", &MBX_B0);
    return 0;
}
连同测试

with Ada.Text_IO;
with Bitbanding;
with System.Storage_Elements;
procedure Bitbanding_Test is
   package Address_IO
     is new Ada.Text_IO.Modular_IO (System.Storage_Elements.Integer_Address);
begin
   Address_IO.Put
     (System.Storage_Elements.To_Integer (Bitbanding.MBX_B0'Address),
      Base => 16);
   Ada.Text_IO.New_Line;
end Bitbanding_Test;

它给出了与C相同的数值结果(
16#22080000#
)。

您是否尝试过编写一个满足您需要的
函数?顺便说一句,我看不出这有什么不起作用的原因,但是如果您尝试了一些东西并且在编译时出错,请发布它。这将使我们更容易知道您想要完成什么。您是否尝试过编写一个满足您需要的
函数
?顺便说一句,我看不出这有什么不起作用的原因,但是如果您尝试了一些东西并且在编译时出错,请发布它。这会让我们更容易知道你想要完成什么。好吧,我想我在常量和静态之间被愚弄了,当我阅读RM时,我认为静态规则(不允许用户定义子程序)适用,我甚至没有尝试过函数。我不知道你能把一个记录传遍整个记忆,我想它们可能只有漏洞,我会调查这种可能性。谢谢。我想我理解你关于唱片的想法,我想我不会这么做。已存在打包RCC寄存器组的记录,每条总线一个寄存器,每个外设一个寄存器位。我添加了相反的一个位,你在外设上翻转(原子)一个位,它启用外设,而你不记得(或浏览文档)它插入了什么总线。常量和静态是C-isms,并不完全适用于Ada。如果你是从C来的,你需要做一些忘却的事情(对我来说,这感觉像是在康复!),但是当Ada的方法感觉更简单、更自然时,你就会知道你已经达到了目的。哦,不要忽视像“重命名”这样的可能性。。。我会在答案中举一个例子。@BrianDrummond Ada有一个“静态”的概念,尽管它不像C++/Java;静态值是编译器在编译时可以计算出来的值。某些构造需要静态值。OP是正确的,在需要静态值的地方,不能有用户定义的子程序。但是
'Address
子句不需要地址的静态值。我想这可能就是他所指的。我不是从任何地方“来”的,我一生中使用过20多种语言。我想在位带中我仍然可以使用记录,它们会使用大量的内存地址空间(因为每个位将占用8位),这是不寻常的,但可行的,但我还不知道我是否会这样做,我认为它对1位字段最有用(在寄存器空间中,我的意思是,在内存空间中有更多)。好的,我想我在常量和静态之间被愚弄了,当我阅读RM时,我虽然应用了静态规则(不允许用户定义子程序),但我甚至没有尝试过函数。我不知道你能把一个记录传遍整个记忆,我想它们可能只有漏洞,我会调查这种可能性。谢谢