error del enlazador al usar Atmel Studio con el proyecto C ++

0

He creado un proyecto simple de C ++ con Studio 7.0.1006. Luego, usando "Agregar clase", agregué una clase simple llamada CGPIO.

A esta clase agregué un método público llamado Inicializar. El código se compila y se ejecuta hasta que agrego el siguiente código a main.cpp para crear una instancia de un objeto CGPIO: CGPIO* pGPIO = new CGPIO() .

La compilación de los resultados del programa en una "referencia indefinida a '_sbrk' error". Un programa más complejo generó una referencia indefinida a otras rutinas (por ejemplo, _exit, _close, _read, etc.).

He intentado jugar con la configuración del enlazador, específicamente No usar archivos estándar y No usar bibliotecas predeterminadas . Al seleccionar No usar bibliotecas predeterminadas , el error _sbrk desaparece, pero aparece una referencia indefinida a __libc_init_array.

No pude encontrar mucha información sobre los programas de C ++ para la serie SAMDxx. ¿Hay un buen ejemplo de trabajo para empezar? ¿Debo agregar una biblioteca diferente a la configuración del enlazador?

    
pregunta tomontee

3 respuestas

1

Mencionas serie D de Microcontroladores basados en SMART ARM de Atmel. Dado que estos errores aparecen en la compilación, es poco probable que el problema se limite a la serie. Siempre busco primero el error en lugar de ejemplos para un microcontrolador en particular. El fabricante de proyectos de muestra es mejor como un salto punto que una explicación de un problema, y puede que no haya mucho publicado por otros.

Entonces, centrándose en el error: una búsqueda encuentra los mismos errores en un Modelo diferente, en un entorno diferente . También aquí . Es posible que las llamadas al sistema (_sbrk) que se definirían en un sistema Unix no estén definidas en un microcontrolador, así que sí, debe agregar las definiciones. Atmel tiene posibilidades (# 10) : el rdimon y nosys . La introducción de nosys en el proyecto parece resolver el problema.

    
respondido por el MBerka
0

El nuevo operador de C ++ se basa en la asignación de memoria dinámica, por ejemplo, a través de malloc (también son posibles implementaciones alternativas que usan sbrk directamente). La biblioteca estándar de C integra una implementación de malloc, pero no sabe qué memoria usar. La biblioteca C estándar usa la función sbrk para adquirir algo de memoria del sistema subyacente. En un entorno alojado, el sistema operativo proporciona esta función. Pero en un entorno independiente, usted debe definir esta función. Después de todo, usted es el único que sabe cuál debe ser el diseño de la memoria.

Dependiendo de la biblioteca de C estándar que use, hay diferentes opciones. Supongo que estás usando newlib (muy popular para los sistemas integrados). En este caso, podría proporcionar una implementación malloc alternativa en lugar de proporcionar la función sbrk y usar la implementación de newlib. El siguiente código debería funcionar más o menos. Esto proporciona la versión reentrante de malloc. Desde lo alto de mi cabeza, no estoy seguro de cómo debe verse la definición de función no reentrante o sbrk.

#define HEAP_SIZE    512

uint8_t heap[HEAP_SIZE];
size_t heap_idx = 0;

// Not sure what this has to be called. Try some of the following:
// void * sbrk(int size) {
// void * _sbrk(int size) {
void * _malloc_r(struct _reent * re, size_t size) {
   void * ret = NULL;

   if (heap_idx + size < HEAP_SIZE)
   {
      ret = &heap[heap_idx];
      heap_idx += size;
   }

   return ret;
}

También hay un código de ejemplo en el manual de newlib que utiliza toda la RAM que no se usa estáticamente como montón. También hay otros syscalls (salir, cerrar, leer ...) que pueden ser útiles para implementar. Consulte el capítulo 12 'syscalls' en el manual de newlib . Eso también debería ocuparse de los otros símbolos indefinidos. Si no puede proporcionar estos syscalls (por ejemplo, no tiene un sistema de archivos), no puede usar ciertas funciones. Por ejemplo, fopen necesita algunos syscalls como abrir, cerrar, fstat ...

Para un sistema completamente funcional, es probable que también desee proporcionar implementaciones de forma gratuita, calloc y realloc. También tengo que agregar la advertencia de repetición: la asignación dinámica en sistemas integrados es increíblemente peligrosa. Si no sabe exactamente lo que está haciendo, probablemente debería atenerse a las asignaciones estáticas. Eso también es posible con C ++. Por ejemplo, podría crear una instancia de su clase como esta:

CGPIO pGPIO();

En este caso, el objeto se asigna en la pila y se destruirá tan pronto como la variable salga de su alcance. Pequeño bono: si no usa nuevo, probablemente no tenga que agregar una implementación sbrk o malloc.

    
respondido por el erebos
-1

La función malloc del lenguaje C y el operador new del lenguaje C ++ requieren un administrador de memoria que pueda realizar Asignaciones dinámicas de memoria en tiempo de ejecución. El administrador de memoria suele ser una combinación de hardware especial (la unidad de administración de memoria, MMU) y la ejecución de software especial (normalmente) dentro de un sistema operativo como Linux, Windows, MacOS, etc. Sin un administrador de memoria, no puede usar la función malloc de C ni el operador nuevo de C ++ en sus programas C / C ++.

Tenga en cuenta que el software escrito para sistemas integrados generalmente se ejecuta "directamente en la plancha", es decir, no hay ningún sistema operativo que (a) administre el hardware y (b) el software de capa de aplicación "hosts" escrito en C ++. En consecuencia, cuando se usa C ++ para crear software para un entorno de sistema integrado sin publicar, varias características del lenguaje C ++ como el operador "nuevo", la herencia virtual, etc., generalmente no se pueden utilizar en esas plataformas. De hecho, hay que abandonar tantos elementos del lenguaje C ++ que a menudo terminas con un programa que se parece más a un programa C que a un programa C ++.

    
respondido por el Jim Fischer

Lea otras preguntas en las etiquetas