繁体   English   中英

如何使Ada中的常数函数?

[英]how to make constant function in Ada?

我正在使用具有位带的ARM系统。 这涉及到计算地址,以及定义要计算其地址的对象。 我想定义一个函数来计算这些地址,但是我无法真正找到绕过该语言的方法。 我能想到的最好的方法是将参数输入到计算中的通用程序包。 问题之一是,我必须(嗯,也许您可​​以纠正我,我是一个初学者)在2个单独的语句中使用它,一个用于定义实例化的包,另一个用于使用它。 那么有没有那么复杂的方法呢? 而且也不太冗长吗? 我觉得我正在用不必要的东西涂抹文件。

到目前为止,这是我自带的:

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_Enable_Register声明为一条记录,它的组成部分之一是一个名为RCC_Enable或只是Enable的布尔值,因为可以将其寻址为RCC_Enable_Register.Enable 有用于定义记录中每个组件的地址,布局和大小的标准语法。

由于合格的表达式(如RCC_Enable_Register.Enable会变得冗长,因此可以使用“重命名”将其简化,例如

RCC_Enable   : Boolean renames RCC_Enable_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;
}

我的(部分)Ada是

private with System.Storage_Elements;

package Bitbanding is

   MBX_B0 : Boolean with Atomic, Size => 32;

private

   subtype Bit_Number is Integer range 0 .. 15;

   --  Register is the address of the register we are interested in.
   --  Register_Base is the start of the memory mapped to registers.
   --  Bit is the bit number within the register.
   --  Alias_Base is the start of the memory area where each
   --    32-bit word is mapped to one bit of the actual registers.
   --  The result is the address to which Register/Bit_Number is mapped.
   function To_Address
     (Register      : Natural;
      Register_Base : Natural;
      Bit           : Bit_Number;
      Alias_Base    : Natural) return System.Address
     is (System.Storage_Elements.To_Address
           (System.Storage_Elements.Integer_Address
              (Alias_Base
                 + (Register - Register_Base) * 32
                 + Bit * 4)));

   --  These are the names in the ARM example; they are not good.
   BITBAND_SRAM_REF : constant := 16#2000_0000#;
   BITBAND_SRAM_BASE : constant := 16#2200_0000#;

   MAILBOX : constant := 16#2000_4000#;

   for MBX_B0'Address use To_Address (Register      => MAILBOX,
                                      Register_Base => BITBAND_SRAM_REF,
                                      Bit           => 0,
                                      Alias_Base    => BITBAND_SRAM_BASE);

end Bitbanding;

连同测试

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# )。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM