Attribut : pack_mode
Le pragma définit la manière dont une structure de données est compressée lors de l'allocation. L'attribut doit être inséré au-dessus de la structure de données et affecte le compactage de toute la structure.
Syntaxe:
{attribute 'pack_mode' := ' <pack mode value> '}
Emplacement d'insertion : au-dessus de la déclaration de la structure de données
<pack mode value>
<valeur du mode pack> | Méthode d'emballage associée | La description |
---|---|---|
0 | Aligné | Toutes les variables sont affectées à des adresses d'octets. Il n'y a pas de trous de mémoire. |
1 | Aligné sur 1 octet | |
2 | Aligné sur 2 octets | . Il y a
|
4 | Aligné sur 4 octets | . Il y a
|
8 | Aligné sur 8 octets | . Il y a
|
Astuce
Selon la structure, il peut n'y avoir aucune différence dans le mappage de la mémoire des modes individuels. Par exemple, la distribution de la mémoire d'une structure avec le {attribute 'pack mode' := '4'}
le pragma peut correspondre à celui de {attribute 'pack mode' := '8'}
.
Astuce
Réseaux de structures
Si les structures sont combinées dans des tableaux, des octets sont ajoutés à la fin de la structure afin que la structure suivante soit alignée.
Important
Si la Disposition de compatibilité option est sélectionnée dans la configuration du symbole et en même temps l'attribut 'pack_mode'
est utilisé dans le code, des problèmes peuvent survenir en raison d'un désalignement involontaire de la mémoire.
Exemple 1
{attribute 'pack_mode' := '1'} TYPE myStruct: STRUCT Enable: BOOL; Counter: INT; MaxSize: BOOL; MaxSizeReached: BOOL; END_STRUCT END_TYPE
La plage de mémoire pour une variable du type de données myStruct
est alloué "aligné". Si l'adresse de stockage de son composant Enable
est 0x0100
, par exemple, alors la composante Counter
suit à l'adresse 0x0101
, MaxSize
à l'adresse 0x0103
et MaxSizeReached
à l'adresse 0x0104
. Dans le cas de 'pack_mode':=2
, Counter
serait à 0x0102
, MaxSize
à 0x0104
et MaxSizeReached
à 0x0105
.
Exemple 2
STRUCT Var1 : BOOL := 16#01; Var2 : BYTE := 16#11; Var3 : WORD := 16#22; Var4 : BYTE := 16#44; Var5 : DWORD := 16#88776655; Var6 : BYTE := 16#99; Var7 : BYTE := 16#AA; Var8 : DWORD := 16#AA; END_TYPE
pack_mode = 8 | pack_mode = 0 | pack_mode = 1 | pack_mode = 2 | pack_mode = 4 | ||||||
---|---|---|---|---|---|---|---|---|---|---|
Variable | Valeur | Variable | Valeur | Variable | Valeur | Variable | Valeur | Variable | Valeur | |
0 |
|
|
|
|
|
|
|
|
|
|
1 |
|
|
|
|
|
|
|
|
|
|
2 |
|
|
|
|
|
|
|
|
|
|
3 | … |
| … |
| … |
| … |
| … |
|
4 |
|
|
|
|
|
|
|
|
|
|
5 |
|
|
|
| ||||||
6 | … |
| … |
|
|
| ||||
7 | … |
| … |
| … |
| ||||
8 |
|
| … |
| … |
| … |
|
|
|
9 | … |
|
|
|
|
| … |
| … |
|
10 | … |
|
|
|
|
|
|
| … |
|
11 | … |
|
|
|
|
|
|
| … |
|
12 |
|
| … |
| … |
|
|
|
|
|
13 |
|
| … |
| … |
| … |
|
|
|
14 | … |
| … |
| … |
| ||||
15 | … |
| ||||||||
16 |
|
|
|
| ||||||
17 | … |
| … |
| ||||||
18 | … |
| … |
| ||||||
19 | … |
| … |
| ||||||
20 | ||||||||||
21 | ||||||||||
22 | ||||||||||
23 | ||||||||||
24 | ||||||||||
25 | ||||||||||
26 | ||||||||||
27 | ||||||||||
28 | ||||||||||
29 | ||||||||||
30 | ||||||||||
31 |
Exemple 3
STRUCT Var1 : BYTE := 16#01; Var2 : LWORD := 16#11; Var3 : BYTE := 16#22; Var4 : BYTE := 16#44; Var5 : DWORD := 16#88776655; Var6 : BYTE := 16#99; Var7 : BYTE := 16#AA; Var8 : WORD := 16#AA; END_TYPE
pack_mode = 8 | pack_mode = 0 | pack_mode = 1 | pack_mode = 2 | pack_mode = 4 | ||||||
---|---|---|---|---|---|---|---|---|---|---|
Variable | Valeur | Variable | Valeur | Variable | Valeur | Variable | Valeur | Variable | Valeur | |
0 |
|
|
|
|
|
|
|
|
|
|
1 |
|
|
|
| ||||||
2 | … |
| … |
|
|
| ||||
3 | … |
| … |
| … |
| ||||
4 | … |
| … |
| … |
|
|
| ||
5 | … |
| … |
| … |
| … |
| ||
6 | … |
| … |
| … |
| … |
| ||
7 | … |
| … |
| … |
| … |
| ||
8 |
|
| … |
| … |
| … |
| … |
|
9 | … |
|
|
|
|
| … |
| … |
|
10 | … |
|
|
|
|
|
|
| … |
|
11 | … |
|
|
|
|
|
|
| … |
|
12 | … |
| … |
| … |
|
|
|
|
|
13 | … |
| … |
| … |
| … |
|
|
|
14 | … |
| … |
| … |
| … |
| ||
15 | … |
|
|
|
|
| … |
| ||
16 |
|
|
|
|
|
|
|
|
|
|
17 |
|
|
|
|
|
|
|
| … |
|
18 | … |
| … |
|
|
| … |
| ||
19 | … |
| … |
| ||||||
20 |
|
|
|
| ||||||
21 | … |
|
|
| ||||||
22 | … |
|
|
| ||||||
23 | … |
| … |
| ||||||
24 |
|
| ||||||||
25 |
|
| ||||||||
26 |
|
| ||||||||
27 | … |
| ||||||||
28 | ||||||||||
29 | ||||||||||
30 | ||||||||||
31 |
Comportement sans 'pack-mode'
Si 'pack-mode'
n'est pas utilisé, le compilateur utilise généralement le mode pack 4 ou 8, selon la description du périphérique. Dans chaque cas, un mode pack particulièrement avantageux pour le processeur est utilisé pour permettre l'accès à la mémoire. Ceci est également appelé alignement naturel ou alignement naturel des données
Effets négatifs lors de l'utilisation 'pack-mode'
Un accès mémoire non aligné peut être le résultat de l'utilisation de l'attribut 'pack_mode'
. Cela signifie, par exemple, qu'un type de données d'une taille de 4 octets se trouve alors à une adresse qui n'est pas divisible par 4. Normalement, sur un système 32 bits, un type de données 32 bits peut être lu et écrit avec un accès unique à la mémoire. Sur certaines plateformes, par exemple sur les plateformes ARM, cela n'est possible que lorsque cette valeur est alignée en mémoire. Sur d'autres plateformes, il se peut que l'accès soit possible mais qu'il s'effectue beaucoup plus lentement.
{attribute 'pack_mode':=1} TYPE DUT STRUCT by1 : BYTE; dw1 : DWORD; END_STRUCT END_TYPE
Sur une plate-forme ARM, la valeur dw1
ne peut pas être lu avec un seul accès. Lorsqu'une tentative est faite pour accéder directement à cet élément, le processeur ARM lève une exception.
Hypothèse : L'accès en lecture suivant est effectué : dwTest := dut1.dw1;
Pour cet accès au DWORD dw1
, quatre accès mémoire sont nécessaires car chaque octet est lu, décalé et disjoncté individuellement. Le flux est un peu le même que dans l'exemple suivant dans lequel un DWORD
est généré à partir d'un tableau de quatre octets :
dwHelp := bytes[0]; dwResult := dwHelp; dwHelp := bytes[1]; dwHelp := SHL(dwHelp, 8); dwResult := dwResult OR dwHelp; dwHelp := bytes[2]; dwHelp := SHL(dwHelp, 16); dwResult := dwResult OR dwHelp; dwHelp := bytes[3]; dwHelp := SHL(dwHelp, 24); dwResult := dwResult OR dwHelp;
Évidemment, ce type d'accès est beaucoup plus lent que l'accès à un DWORD
, qui est correctement aligné dans la mémoire.
pdw := ADR(dut1.dw1); dwTest := pdw^;
Cependant, le compilateur ne générera pas l'accès de l'exemple lorsque ce type de membre est accédé au moyen d'un pointeur. Cela signifie que le code suivant génère une exception sur une plate-forme ARM.
pdw := ADR(dut1.dw1); dwTest := pdw^;
Pour des raisons de performances, il faut donc éviter de travailler avec des structures qui ne sont pas naturellement alignées.
Une structure emballée ne doit pas contenir une structure non emballée.