10 votos

Código de inicio de metal desnudo para la inicialización de la región .xs de Cortex M3

He desarrollado inspirado a partir de aquí un metal desnudo código de inicio para arm cortex M3. Sin embargo, me encuentro con el siguiente problema: supongamos que declaro no inicializado la variable global, digamos de tipo unsigned char principal.c

#include ...
unsigned char var; 
...
int main()
{
 ...
}

esto hace que el .bss región en STM32 f103 partir de _BSS_START=0x20000000 y terminando en _BSS_END = 0x20000001. Ahora, la puesta en marcha de código

    unsigned int * bss_start_p = &_BSS_START; 
    unsigned int * bss_end_p = &_BSS_END;

    while(bss_start_p != bss_end_p)
    {
        *bss_start_p = 0;
        bss_start_p++;
    }

intenta inicializar a cero todo .bss región. Sin embargo, dentro de ese bucle while el puntero se incrementa con 4 bytes, por lo tanto, después de un paso bss_start_p = 0x20000004 por lo tanto siempre será diferente de bss_end_p que lleva a un bucle infinito etc.

¿Hay alguna solución estándar a esto? Soy supongo que a la "fuerza" de alguna manera la dimensión de la .bss región para ser un múltiplo de 4? O debo usar un puntero a unsigned char a caminar a través .bss región? Quizás algo como:

    unsigned char * bss_start_p = (unsigned char *)(&_BSS_START); 
    unsigned char * bss_end_p = (unsigned char *)(&_BSS_END);

    while(bss_start_p != bss_end_p)
    {
        *bss_start_p = 0;
        bss_start_p++;
    }

15voto

bitsmack Puntos 5415

Como se sospecha, de que esto está sucediendo porque el unsigned int tipo de datos es de 4 bytes de tamaño. Cada *bss_start_p = 0; declaración de la realidad borra cuatro bytes de la sev área.

El bss rango de memoria debe estar alineada correctamente. Usted puede simplemente definir _BSS_START y _BSS_END por lo que el tamaño total es un múltiplo de cuatro, pero esto es generalmente manejado por lo que el linker script para definir el inicio y ubicaciones de las paradas.

Como ejemplo, aquí está el enlace de la sección en uno de mis proyectos:

.bss (NOLOAD) : ALIGN(4)
{
    __bss_start__ = .;
    *(.bss)
    . = ALIGN(4);
    __bss_end__ = .;
} >RAM

El ALIGN(4) declaraciones de cuidar de las cosas.

También, usted puede desear cambiar

while(bss_start_p != bss_end_p)

a

while(bss_start_p < bss_end_p).

Esto no impedirá que el problema (ya que podría estar limpiando 1-3 más bytes que desea), pero podría minimizar el impacto :)

4voto

ilkkachu Puntos 446

La solución estándar es memset():

#include <string.h>
memset(&_BSS_START, 0, &_BSS_END - &_BSS_START)

Si no puede usar la biblioteca estándar, entonces usted tendrá que decidir si está bien en su caso a la redonda del tamaño del área de memoria de hasta 4 bytes, y seguir usando unsigned int *; o si usted necesita para ser estrictos, en cuyo caso sería necesario el uso de unsigned char *.

Si usted redondear el tamaño, como en el primer bucle, a continuación, bss_start_p de hecho puede llegar a mayor bss_end_p , pero eso es fácil lidiar con un menos que la comparación < en lugar de una desigualdad de la prueba.

Por supuesto, también se puede ocupar la mayor parte del área de memoria de 32 bits transferencias, y sólo en el último par de bytes de 8 bits transferencias, pero eso es más trabajo para poca ganancia, especialmente cuando es sólo un pedazo de código de inicio.

4voto

dahulius Puntos 11

Simplemente cambie != a < . Por lo general, ese es un mejor enfoque, ya que trata problemas como este.

i-Ciencias.com

I-Ciencias es una comunidad de estudiantes y amantes de la ciencia en la que puedes resolver tus problemas y dudas.
Puedes consultar las preguntas de otros usuarios, hacer tus propias preguntas o resolver las de los demás.

Powered by:

X