Comment puis-je utiliser malloc()
et free()
fonctionner dans un PIC? J'ai vérifié l'en- stdlib.h
tête et il n'y en a aucune mention. J'utilise MCC18.
Quelqu'un a-t-il dû les utiliser?
J'en ai besoin car je porte une bibliothèque de Windows XP vers le PIC. Le guide de portage dit de
adapter les fonctions spécifiques du système d'exploitation à mes PIC
Mais je ne sais pas "traduire" les fonctions malloc()
et free()
.
Réponses:
Dans de nombreuses applications, il faudra allouer de la mémoire, mais pas besoin de libérer quoi que ce soit tout en conservant quelque chose qui a été alloué après. Sur un tel système, il suffit d'utiliser l'éditeur de liens pour définir un tableau en utilisant toute la RAM disponible, définir un pointeur sur le début de ce tableau, puis utiliser une fonction malloc facile et agréable:
Agréable et facile, et juste deux octets au total pour tout nombre d'allocations. Appeler free () sur un bloc désallouera ce bloc et tout ce qui le suivra.
Des modèles d'allocation légèrement plus compliqués peuvent être gérés à l'aide de deux pointeurs - l'un qui alloue des éléments du bas de la mémoire vers le haut, et l'autre allant du haut de la mémoire vers le bas. Il est également possible d'utiliser un récupérateur de place compacté si les données du tas sont homogènes et que l'on sait où se trouvent toutes les références externes.
la source
malloc()
dans les microcontrôleurs est généralement considéré comme une "mauvaise chose". Mais, si vous en avez absolument besoin, vous voudrez trouver une version tierce.Si vous avez de la chance, le code que vous portez peut ne pas dépendre de la réutilisation de blocs de mémoire. Si tel est le cas, vous pouvez écrire un allocateur simple qui renvoie un pointeur dans un tampon RAM, puis avance le pointeur de la taille de bloc demandée.
J'ai déjà utilisé cette approche avec succès dans le portage de bibliothèques PC vers des microcontrôleurs.
Ci-dessous, vous devez configurer l'allocateur avec
my_malloc_init()
et allouer de la mémoire avecmy_malloc()
.my_free()
est là pour satisfaire la dépendance mais ne fait rien. Finalement, vous manquerez d'espace, bien sûr.Pour que cela fonctionne, vous devrez mesurer la mémoire la plus défavorable de votre code (faites-le sur un PC si possible), puis configurez-la en
HEAP_SIZE
conséquence. Avant d'entrer dans la partie de votre bibliothèque nécessitant une mémoire dynamique, appelezmy_malloc_init()
. Avant de réutiliser, assurez-vous que rien ne pointe toujoursheap
.(Remarque: dans le monde réel, vous devrez peut-être envisager l'alignement du pointeur, c'est-à-dire arrondir à
heap_ptr
2 ou 4 octets)Une autre option consiste à utiliser une structure d'allocation plus simple que celle
malloc()
fournie habituellement, comme une FreeList , bien que cela ne vous permette pas d'allouer des blocs de taille variable.la source
Ce n'est guère une réponse à votre question, mais l'allocation dynamique de mémoire est généralement mal vue sur les petits environnements RAM et en l'absence d'un système d'exploitation (par exemple dans le monde des microcontrôleurs) ... l'espace de stockage dont vous disposez dans un environnement intégré est généralement mesuré en centaines d'octets ...
L'implémentation de malloc et de free est essentiellement la maintenance d'une liste chaînée de structures de "segment libre", et comme vous pouvez l'imaginer, les métadonnées associées aux segments libres ne sont pas négligeables par rapport à la quantité de mémoire généralement disponible ... c'est-à-dire la "surcharge" "La gestion d'un pool de mémoire dynamique consomme une quantité importante des ressources disponibles.
la source
Je ne sais pas si la bibliothèque standard C18 prend en charge
malloc
etfree
, mais Microchip App Note AN914 montre comment vous pouvez implémenter la vôtre.Dans tous les cas, Thomas et d'autres affiches ont suggéré que l'utilisation de la mémoire dynamique sur les PIC avec leur très petit espace RAM est lourde de dangers. Vous pouvez rapidement manquer d'espace contigu en raison du manque de gestionnaires de mémoire virtuelle plus avancés que les systèmes d'exploitation complets vous offrent, entraînant des allocations et des plantages défaillants. Pire encore, cela peut ne pas être déterministe et sera probablement difficile à déboguer.
Si ce que vous faites est vraiment déterminé dynamiquement au moment de l'exécution (rare pour la plupart des choses intégrées), et que vous n'avez besoin d'allouer de l'espace qu'à quelques occasions très spéciales , je pourrais voir
malloc
etfree
être acceptable.la source
Eh bien, quelle est la taille de votre PIC en termes de mémoire?
malloc est une façon très inefficace d'allouer de la mémoire. Le problème avec cela est que la mémoire peut devenir fragmentée avec des libérations fréquentes et des mallocs et avec seulement quelques kilo-octets de mémoire, les échecs d'allocation sont trop fréquents. Il est très probable que si vous utilisez une puce plus petite ou un PIC18 antérieur, il n'y a pas de support pour malloc, car Microchip le considérait comme très difficile à mettre en œuvre (ou peut-être même impossible dans certains cas) ou pas assez utilisé pour qu'il soit ça vaut le coup. Sans parler de cela, mais c'est aussi assez lent, vous regardez 1 cycle pour utiliser un tampon statique déjà disponible et 100 à 1 000 cycles pour faire un malloc.
Si vous souhaitez allouer statiquement, créez des choses comme un tampon pour vos fonctions sprintf (le cas échéant, environ 128 octets), un tampon pour votre carte SD (le cas échéant), et ainsi de suite, jusqu'à ce que vous supprimiez le besoin de malloc. Idéalement, vous ne l'utilisez que là où vous en avez absolument besoin et ne pouvez pas vous passer de l'allocation statique, mais ces situations sont généralement rares et peuvent être un signe que vous devriez envisager des microcontrôleurs plus gros / plus puissants.
Et si vous développez / portez un "système d'exploitation" sur le PIC18 et s'il prend en charge les microcontrôleurs, il prend probablement en charge l'allocation statique. Par exemple, SQLite3 prend en charge l'allocation statique - vous lui allouez un grand tableau de tampons et il l'utilise dans la mesure du possible, même si ce n'est pas pour les microcontrôleurs. Si ce n'est pas le cas, êtes-vous sûr qu'il est conçu pour un petit PIC18?
la source
Si vous envisagez
malloc()
etfree()
pour votre logiciel intégré, je vous suggère de jeter un œil à uC / OS-II etOSMemGet()
etOSMemPut()
. Alorsmalloc()
que vous allouez un bloc de mémoire arbitraire,OSMem*()
donnez-vous un bloc de taille fixe à partir d'un pool pré-alloué. Je trouve cette approche un bon équilibre entre la flexibilitémalloc()
et la robustesse de l'allocation statique.la source
AFAIK, pour le faire correctement, vous devez vraiment regarder un appareil avec une sorte d'unité de gestion de la mémoire (MMU). Bien qu'il existe des mécanismes d'allocation dynamique pour la série PIC18, ils ne seront pas vraiment solides - et parlant comme quelqu'un qui a travaillé sur un firmware qui repousse les limites de la série PIC18, je peux dire que vous n'allez pas obtenir une application importante là-dedans si vous dépensez tous les frais généraux sur un gestionnaire de mémoire.
Meilleure solution: essayez de comprendre ce qu'elle fait et pourquoi elle a besoin d'une allocation dynamique. Voyez si vous ne pouvez pas le re-factoriser pour qu'il fonctionne avec l'allocation statique. (Il se peut que ce ne soit tout simplement pas possible - si la bibliothèque / application est conçue pour faire quelque chose qui évolue librement ou qui n'a pas de limites de la quantité d'entrée qu'elle peut accepter.) Mais parfois, si vous pensez vraiment sur ce que vous essayez de faire, vous pourriez trouver qu'il est possible (et peut-être même assez facile) d'utiliser l'allocation statique à la place.
la source