DrPi
2021-02-16 15:25:43 UTC
Bonjour,
J'utilise svd2ada pour générer les fichiers de spécification des
périphériques d'un micro-contrôlleur.
Par exemple pour un GPIO :
type GPIO_Peripheral is record
-- GPIO data register
DR : aliased HAL.UInt32;
-- GPIO direction register
GDIR : aliased GDIR_Register;
-- GPIO data register SET
DR_SET : aliased HAL.UInt32;
-- GPIO data register CLEAR
DR_CLEAR : aliased HAL.UInt32;
-- GPIO data register TOGGLE
DR_TOGGLE : aliased HAL.UInt32;
end record
with Volatile;
for GPIO_Peripheral use record
DR at 16#0# range 0 .. 31;
GDIR at 16#4# range 0 .. 31;
DR_SET at 16#84# range 0 .. 31;
DR_CLEAR at 16#88# range 0 .. 31;
DR_TOGGLE at 16#8C# range 0 .. 31;
end record;
-- GPIO
GPIO1_Periph : aliased GPIO_Peripheral
with Import, Address => GPIO1_Base;
-- GPIO
GPIO2_Periph : aliased GPIO_Peripheral
with Import, Address => GPIO2_Base;
-- GPIO
GPIO3_Periph : aliased GPIO_Peripheral
with Import, Address => GPIO3_Base;
-- GPIO
GPIO5_Periph : aliased GPIO_Peripheral
with Import, Address => GPIO5_Base;
J'ai écrit une couche d'abtraction :
type t_GPIO_Peripheral_Access is access all GPIO_Peripheral;
GPIO_1 : GPIO_Peripheral renames GPIO1_Periph;
GPIO_2 : GPIO_Peripheral renames GPIO2_Periph;
GPIO_3 : GPIO_Peripheral renames GPIO3_Periph;
GPIO_5 : GPIO_Peripheral renames GPIO5_Periph;
subtype t_gpio_pin is Integer range 0..31;
procedure Write(gpio : out GPIO_Peripheral; gpio_pin : in
t_gpio_pin; value : in Boolean)
with Inline;
procedure Set(gpio : out GPIO_Peripheral; gpio_pin : in t_gpio_pin)
with Inline;
procedure Clear(gpio : out GPIO_Peripheral; gpio_pin : in t_gpio_pin)
with Inline;
procedure Toggle(gpio : out GPIO_Peripheral; gpio_pin : in t_gpio_pin)
with Inline;
function Get(gpio : in GPIO_Peripheral; gpio_pin : in t_gpio_pin)
return Boolean
with Inline;
J'utilise cette API comme ceci :
Write(GPIO_1, 2, True);
Set(GPIO_2, 3);
Cela fonctionne bien; Mais est-ce correct ?
Les procédures Write, Set... ne devraient-elles pas utiliser un access ?
Comme ceci :
procedure Write(gpio : out access all GPIO_Peripheral; ...);
En avançant sur mon projet, j'ai créé un tableau de structures comme ceci :
type t_Gpio_Infos is record
GPIO_Periph : gpio.GPIO_Peripheral; -- <=== GPIO_Peripheral
GPIO_Pin : gpio.t_gpio_pin;
Pad_Mux : t_PadMux;
end record;
type t_Gpio_Infos_Array is array (t_Gpio_Pad_Name) of t_Gpio_Infos;
Gpio_Infos_Array : constant t_Gpio_Infos_Array :=
(
-- GPIO 1 Pad_Mux => Alt5
PAD_GPIO_AD_B0_00 => (GPIO_Periph => gpio.GPIO_1, ...),
...
);
La structure donne des infos de GPIO pour une patte du micro-contrôlleur.
Le tableau donne les indications pour toutes les pattes concernées.
J'ai également des fonctions d'abstraction qui retournent les infos du
tableau. Par exemple.
function GPIO_Periph(Pad_Name : t_Gpio_Pad_Name) return
gpio.t_GPIO_Peripheral is
begin
return Gpio_Infos_Array(Pad_Name).GPIO_Periph;
end GPIO_Periph;
Quand je fais
Set(GPIO_Periph(xxx), 2);
ça ne marche pas.
J'ai remplacé la définition du record par ceci :
type t_Gpio_Infos is record
GPIO_Periph : gpio.t_GPIO_Peripheral_Access; -- <=== Access
GPIO_Pin : gpio.t_gpio_pin;
Pad_Mux : t_PadMux;
end record;
J'ai bien sûr modifié le tableau et les fonctions en conséquence.
Maintenant, lorsque je fais
gpio.Set(Gpio_Periph(Led).all, 2);
ca marche.
Je ne comprends pas vraiment ce qui se passe ici.
Je comprends l'utilisation de access. D'où ma question du début : les
procédures Write, Set... devraient-elles utiliser un access ?
Mais je ne comprends pas pourquoi, sans access, ça marche, ou pas.
Set(GPIO_2, 3); -- <== Fonctionne
Set(GPIO_Periph(xxx), 2); -- <== Fonctionne pas
Quand je dis que cela ne fonctionne pas, c'est simplement que tout se
passe comme si l'appel à la procédure n'était pas fait (je n'ai pas
vérifié au débugger).
Je n'ai pas d'erreur de compilation.
J'utilise GNAT community 2020 sur plateforme ARM.
Même si j'ai un code fonctionnel (en utilisant partiellement access),
j'ai peur de passer à coté d'un principe fondamental.
Cordialement,
Nicolas
J'utilise svd2ada pour générer les fichiers de spécification des
périphériques d'un micro-contrôlleur.
Par exemple pour un GPIO :
type GPIO_Peripheral is record
-- GPIO data register
DR : aliased HAL.UInt32;
-- GPIO direction register
GDIR : aliased GDIR_Register;
-- GPIO data register SET
DR_SET : aliased HAL.UInt32;
-- GPIO data register CLEAR
DR_CLEAR : aliased HAL.UInt32;
-- GPIO data register TOGGLE
DR_TOGGLE : aliased HAL.UInt32;
end record
with Volatile;
for GPIO_Peripheral use record
DR at 16#0# range 0 .. 31;
GDIR at 16#4# range 0 .. 31;
DR_SET at 16#84# range 0 .. 31;
DR_CLEAR at 16#88# range 0 .. 31;
DR_TOGGLE at 16#8C# range 0 .. 31;
end record;
-- GPIO
GPIO1_Periph : aliased GPIO_Peripheral
with Import, Address => GPIO1_Base;
-- GPIO
GPIO2_Periph : aliased GPIO_Peripheral
with Import, Address => GPIO2_Base;
-- GPIO
GPIO3_Periph : aliased GPIO_Peripheral
with Import, Address => GPIO3_Base;
-- GPIO
GPIO5_Periph : aliased GPIO_Peripheral
with Import, Address => GPIO5_Base;
J'ai écrit une couche d'abtraction :
type t_GPIO_Peripheral_Access is access all GPIO_Peripheral;
GPIO_1 : GPIO_Peripheral renames GPIO1_Periph;
GPIO_2 : GPIO_Peripheral renames GPIO2_Periph;
GPIO_3 : GPIO_Peripheral renames GPIO3_Periph;
GPIO_5 : GPIO_Peripheral renames GPIO5_Periph;
subtype t_gpio_pin is Integer range 0..31;
procedure Write(gpio : out GPIO_Peripheral; gpio_pin : in
t_gpio_pin; value : in Boolean)
with Inline;
procedure Set(gpio : out GPIO_Peripheral; gpio_pin : in t_gpio_pin)
with Inline;
procedure Clear(gpio : out GPIO_Peripheral; gpio_pin : in t_gpio_pin)
with Inline;
procedure Toggle(gpio : out GPIO_Peripheral; gpio_pin : in t_gpio_pin)
with Inline;
function Get(gpio : in GPIO_Peripheral; gpio_pin : in t_gpio_pin)
return Boolean
with Inline;
J'utilise cette API comme ceci :
Write(GPIO_1, 2, True);
Set(GPIO_2, 3);
Cela fonctionne bien; Mais est-ce correct ?
Les procédures Write, Set... ne devraient-elles pas utiliser un access ?
Comme ceci :
procedure Write(gpio : out access all GPIO_Peripheral; ...);
En avançant sur mon projet, j'ai créé un tableau de structures comme ceci :
type t_Gpio_Infos is record
GPIO_Periph : gpio.GPIO_Peripheral; -- <=== GPIO_Peripheral
GPIO_Pin : gpio.t_gpio_pin;
Pad_Mux : t_PadMux;
end record;
type t_Gpio_Infos_Array is array (t_Gpio_Pad_Name) of t_Gpio_Infos;
Gpio_Infos_Array : constant t_Gpio_Infos_Array :=
(
-- GPIO 1 Pad_Mux => Alt5
PAD_GPIO_AD_B0_00 => (GPIO_Periph => gpio.GPIO_1, ...),
...
);
La structure donne des infos de GPIO pour une patte du micro-contrôlleur.
Le tableau donne les indications pour toutes les pattes concernées.
J'ai également des fonctions d'abstraction qui retournent les infos du
tableau. Par exemple.
function GPIO_Periph(Pad_Name : t_Gpio_Pad_Name) return
gpio.t_GPIO_Peripheral is
begin
return Gpio_Infos_Array(Pad_Name).GPIO_Periph;
end GPIO_Periph;
Quand je fais
Set(GPIO_Periph(xxx), 2);
ça ne marche pas.
J'ai remplacé la définition du record par ceci :
type t_Gpio_Infos is record
GPIO_Periph : gpio.t_GPIO_Peripheral_Access; -- <=== Access
GPIO_Pin : gpio.t_gpio_pin;
Pad_Mux : t_PadMux;
end record;
J'ai bien sûr modifié le tableau et les fonctions en conséquence.
Maintenant, lorsque je fais
gpio.Set(Gpio_Periph(Led).all, 2);
ca marche.
Je ne comprends pas vraiment ce qui se passe ici.
Je comprends l'utilisation de access. D'où ma question du début : les
procédures Write, Set... devraient-elles utiliser un access ?
Mais je ne comprends pas pourquoi, sans access, ça marche, ou pas.
Set(GPIO_2, 3); -- <== Fonctionne
Set(GPIO_Periph(xxx), 2); -- <== Fonctionne pas
Quand je dis que cela ne fonctionne pas, c'est simplement que tout se
passe comme si l'appel à la procédure n'était pas fait (je n'ai pas
vérifié au débugger).
Je n'ai pas d'erreur de compilation.
J'utilise GNAT community 2020 sur plateforme ARM.
Même si j'ai un code fonctionnel (en utilisant partiellement access),
j'ai peur de passer à coté d'un principe fondamental.
Cordialement,
Nicolas