AdaCore / Ada_Drivers_Library

Ada source code and complete sample GNAT projects for selected bare-board platforms supported by GNAT.
BSD 3-Clause "New" or "Revised" License
240 stars 141 forks source link

bbc:microbit and Buttons and No_Implicit_Dynamic_Code #272

Closed bjorn-lundin closed 6 years ago

bjorn-lundin commented 6 years ago

The Microbit has 2 buttons. And the MicroBit.Button package has a way of subscribing callbacks to pressed/released events.

But trying to use it I get main.adb:55:33: violation of restriction "No_Implicit_Dynamic_Code" at system.ads:45

Using Gnat Community 2018 for Linux_x64

with Microbit.Display;
with Microbit.Buttons;
with Microbit.Time;

procedure Main is
  use Microbit.Buttons;
  procedure Button_Pressed(Button : Button_Id; State  : Button_State) is
  begin
    case State is
      when Pressed  => Microbit.Display.Set(2,2);
      when Released => Microbit.Display.Clear(2,2);
    end case;
  end Button_Pressed;
  Ok : Boolean := True;
begin
  MicroBit.Display.Clear;
  Ok := Subscribe(Button_Pressed'Unrestricted_Access);
  if Ok then
    Microbit.Display.Set(0,0);
  end if;
  loop
    Microbit.Time.Delay_Ms (200);
  end loop;
end Main;
Fabien-Chouteau commented 6 years ago

Hi @bjorn-lundin

You can have a look here to understand what this error means: No_Implicit_Dynamic_Code

On this platform implicit code is not supported, so you can't use the 'Unrestricted_Access attribute. Instead you should use 'Access, but this will give you another error message: main.adb:21:21: subprogram must not be deeper than access type. Simplified this means that you cannot use an access to a subprogram that is nested in the Main procedure, so what you have to do is move your button pressed procedure into a package.

with Microbit.Buttons; use Microbit.Buttons;

package Plop is
   procedure Button_Pressed (Button : Button_Id; State  : Button_State);
end Plop;
with Microbit.Display;

package body Plop is
  procedure Button_Pressed (Button : Button_Id; State  : Button_State) is
  begin
    case State is
      when Pressed  => Microbit.Display.Set (2, 2);
      when Released => Microbit.Display.Clear (2, 2);
    end case;
  end Button_Pressed;
end Plop;

Regards,