¿Cómo puedo usar malloc()
y free()
funciones en un PIC? He comprobado el stdlib.h
encabezado y no hay mención de ellos. Estoy usando MCC18.
¿Alguien ha tenido que usarlos?
Los necesito porque estoy transfiriendo una biblioteca de Windows XP al PIC. La guía de portabilidad dice a
adaptar las funciones específicas del sistema operativo a mis PIC
Pero no sé cómo "traducir" las funciones malloc()
y free()
.
Respuestas:
En muchas aplicaciones, uno necesitará asignar memoria, pero no necesitará liberar nada mientras mantiene algo que se asignó después. En dicho sistema, todo lo que uno necesita hacer es usar el enlazador para definir una matriz usando toda la RAM disponible, establecer un puntero al inicio de esa matriz y luego usar una función malloc fácil y agradable:
Agradable y fácil, y solo dos bytes de sobrecarga total para cualquier cantidad de asignaciones. Llamar a free () en un bloque desasignará ese bloque y todo lo que sigue.
Se pueden manejar patrones de asignación un poco más complicados mediante el uso de dos punteros: uno que asigna las cosas desde la parte inferior de la memoria hacia arriba y otra desde la parte superior de la memoria hacia abajo. También es posible usar un recolector de basura de compactación si los datos en el montón son homogéneos y uno sabe dónde están todas las referencias externas.
fuente
malloc()
en microcontroladores generalmente se considera una "cosa mala". Pero, si lo necesita absolutamente, entonces querrá encontrar una versión de terceros.Si tiene suerte, el código que está transfiriendo puede no depender de la reutilización de bloques de memoria. Si este es el caso, puede escribir un asignador simple que devuelva un puntero a un búfer de RAM, luego avance el puntero por el tamaño de bloque solicitado.
He utilizado con éxito este enfoque antes de portar bibliotecas de PC a microcontroladores.
A continuación, configuraría el asignador con
my_malloc_init()
y asignaría memoria conmy_malloc()
.my_free()
está ahí para satisfacer la dependencia pero en realidad no hará nada. Eventualmente te quedarás sin espacio, por supuesto.Para que esto funcione, necesitará medir el requisito de memoria del peor de los casos de su código (haga esto en una PC si es posible) y luego configúrelo en
HEAP_SIZE
consecuencia. Antes de ingresar a la parte de su biblioteca que requiere memoria dinámica, llamemy_malloc_init()
. Antes de volver a usar, asegúrese de que nada apunte todavíaheap
.(nota: en el mundo real, es posible que deba considerar la alineación del puntero, es decir, redondear
heap_ptr
en 2 o 4 bytes)Otra opción es usar una estructura de asignación más simple que la que
malloc()
generalmente proporciona, como una Lista Libre , aunque esto puede no permitirle asignar bloques de tamaño variable.fuente
Esta no es una respuesta a su pregunta, pero la asignación dinámica de memoria generalmente está mal vista en entornos RAM pequeños y en ausencia de un sistema operativo (por ejemplo, en el mundo de los microcontroladores) ... el espacio de almacenamiento dinámico que tiene disponible en un entorno integrado es típicamente medido en cientos de bytes ...
La implementación de malloc y free es esencialmente el mantenimiento de una lista vinculada de estructuras de "segmento libre", y como se puede imaginar, los metadatos asociados con los segmentos libres no son insustanciales en comparación con la cantidad de memoria típicamente disponible ... esa es la "sobrecarga" "de administrar una agrupación de memoria dinámica consume una cantidad significativa de los recursos disponibles.
fuente
No sé si la biblioteca estándar C18 admite
malloc
yfree
, pero la nota de aplicación de Microchip AN914 muestra cómo puede implementar la suya.En cualquier caso, Thomas y otros pósters han sugerido que usar memoria dinámica en PIC con su espacio RAM muy pequeño está lleno de peligros. Puede quedarse rápidamente sin espacio contiguo debido a la falta de administradores de memoria virtual más avanzados que los sistemas operativos completos le brindan, lo que lleva a fallas en las asignaciones y fallas. Peor aún, puede no ser determinista, y probablemente será un dolor de depuración.
Si lo que está haciendo está realmente determinado dinámicamente en tiempo de ejecución (raro para la mayoría de las cosas incrustadas), y solo necesita asignar espacio en un par de ocasiones muy especiales , podría ver
malloc
yfree
ser aceptable.fuente
Bueno, ¿qué tan grande es tu PIC en términos de memoria?
malloc es una forma muy ineficiente de asignar memoria. El problema es que la memoria puede fragmentarse con frecuentes liberaciones y mallocs y con solo unos pocos kilobytes de memoria, las fallas de asignación son muy comunes. Es muy probable que si está utilizando un chip más pequeño o un PIC18 anterior, no hay soporte para malloc, ya que Microchip lo consideró muy difícil de implementar (o tal vez incluso imposible en algunos casos) o no lo utilizó lo suficiente como para que sea vale la pena. Sin mencionarlo, pero también es bastante lento, estás buscando 1 ciclo para usar un búfer estático ya disponible y de 100 a 1,000 ciclos para hacer un malloc.
Si desea asignar estáticamente, cree cosas como un búfer para sus funciones sprintf (si corresponde, alrededor de 128 bytes), un búfer para su tarjeta SD (si corresponde), y así sucesivamente, hasta que elimine la necesidad de malloc. Idealmente, solo lo usa donde lo necesita absolutamente y no puede salirse con la asignación estática, pero estas situaciones suelen ser raras y tal vez una señal de que debería estar buscando microcontroladores más grandes / potentes.
Y si está desarrollando / portando un "sistema operativo" en el PIC18 y si es compatible con microcontroladores, probablemente sea compatible con la asignación estática. Por ejemplo, SQLite3 admite la asignación estática: se le asigna una matriz de búfer grande y la usa cuando sea posible, aunque no sea para microcontroladores. Si no es así, ¿estás seguro de que está diseñado para un PIC18 pequeño?
fuente
Si está considerando
malloc()
yfree()
para su software integrado, le sugiero que eche un vistazo a uC / OS-II yOSMemGet()
yOSMemPut()
. Si bien lemalloc()
permite asignar un bloque arbitrario de memoria, leOSMem*()
brinda un bloque de tamaño fijo de un grupo preasignado. Este enfoque me parece un buen equilibrio entre la flexibilidadmalloc()
y la solidez de la asignación estática.fuente
AFAIK, para hacer esto correctamente, realmente necesita estar mirando un dispositivo con algún tipo de unidad de administración de memoria (MMU). Si bien existen mecanismos de asignación dinámica para la serie PIC18, en realidad no van a ser tan sólidos, y hablando como alguien que ha trabajado en firmware que supera los límites de la serie PIC18, puedo decir que no va a obtener una aplicación considerable allí si gastas todos los gastos generales en un administrador de memoria.
Mejor solución: intente comprender qué está haciendo y por qué necesita una asignación dinámica. Vea si no puede volver a factorizarlo para que funcione con asignación estática. (Puede darse el caso de que esto simplemente no sea posible, si la biblioteca / aplicación está diseñada para hacer algo que se escala libremente, o no tiene límites de la cantidad de entrada que puede aceptar). Pero a veces, si realmente piensa sobre lo que está tratando de hacer, es posible que en su lugar sea posible (y posiblemente incluso bastante fácil) usar la asignación estática.
fuente