Explique brevemente el proceso de inicio y el proceso de ejecución del programa del chip.

Tabla de contenido

1. Proceso de inicio de chips

2. Código de inicio

2.1 Definición de pila

2.2 Tabla de vectores

2.3 Procedimiento de reinicio

2.4 Rutina de servicio de interrupción

3. El proceso de ejecución del programa

4. Acceso a datos


1. Proceso de inicio de chips

El inicio del chip consiste en ejecutar el programa inherente dentro del chip (es decir, el código de inicio) después del encendido. Después de que el programa de código de inicio haya establecido el entorno de ejecución, leerá el estado del puerto serie, es decir, cada puerto utilizado por el usuario para descargar el programa, y ​​determinará si el usuario está utilizando el puerto para prepararse para descargar el programa. .

Si el usuario está descargando el programa, el programa del usuario se descarga a la dirección especificada de acuerdo con la solicitud del usuario. Si no se descarga ningún programa, el chip saltará a la entrada del programa de usuario existente de forma predeterminada, entregando así el control del chip al programa de usuario. Si es un chip nuevo sin un programa de usuario, permanece en el ciclo de lectura del estado del puerto serie.

El código de inicio generalmente se escribe en flash, que es un programa que se ejecuta tan pronto como se enciende el sistema. Se ejecuta antes que cualquier código C de usuario. Después del encendido, el procesador armado está en estado armado y se ejecuta en el modo privilegiado. Al mismo tiempo, todas las interrupciones del sistema están desactivadas y la PC obtiene instrucciones de la dirección 0 para su ejecución.

Tomemos el modo de arranque Flash como ejemplo. Después del encendido, el programa que comienza en la dirección 0x0800 0000 se asigna a la dirección 0x0000 0000, y luego el programa comienza a ejecutarse desde 0x0000 0000. El chip leerá un valor de 32 bits de la dirección 0x0000 0000 y lo asignará al puntero de pila SP; luego leerá un valor de 32 bits de la dirección 0x0000 0004 y lo copiará a la PC del puntero del contador del programa, y ​​el programa comenzará a ejecutarse desde el contenido del puntero de la PC.

El código de inicio completa principalmente dos aspectos del trabajo, uno es inicializar el entorno de ejecución, como la tabla de vectores de interrupción, la pila, E/S, etc.; el otro es inicializar la biblioteca c y las aplicaciones de usuario.

2. Código de inicio

Tomando STM32 como ejemplo, echemos un vistazo al proceso desde el encendido del chip hasta la función principal. Los pasos principales son los siguientes:

1. Inicializar el puntero de pila SP=_initial_sp, inicializar PC=Reset_Handler

2. Inicializar la tabla de vectores de interrupción

3. Configurar el reloj del sistema

4. Llame a la función de biblioteca C __main para inicializar la pila de usuario y luego ingrese la función principal

Dado que el proceso de inicio se completa principalmente con el ensamblaje, la mayor parte del contenido de inicio de STM32 se encuentra en el archivo de inicio. Ahora tome startup_stm32f103xe.s como ejemplo (el principio de otros tipos de archivos de inicio es similar).

2.1 Definición de pila

1. ApilarApilar

La función de la pila es guardar variables locales, llamadas a funciones, parámetros de funciones, etc., y el tamaño de la pila no puede exceder el tamaño de la SRAM interna. Cuando el programa es grande, el tamaño de la pila debe modificarse, de lo contrario, pueden ocurrir errores HardFault.

Línea 33: indica que el tamaño de la pila es 0x00000400 (1KB), y EQU es una pseudoinstrucción, lo que equivale a definir en C.

Línea 35: abra una sección de espacio de datos de lectura y escritura, y la pseudoinstrucción ARER indica que un segmento de código o segmento de datos se definirá a continuación. Aquí está la sección de datos de definición. La palabra clave después de ARER indica los atributos de este segmento. El nombre del segmento es STACK, que se puede nombrar arbitrariamente; NOINIT significa no inicializado; READWRITE significa legible y escribible, y ALIGN=3 significa alineación de acuerdo con 8 bytes.

Línea 36: SPACE se usa para asignar un espacio de memoria continuo con un tamaño igual a Stack_Size, en bytes.

Línea 37: __initial_sp representa la dirección de la parte superior de la pila. La pila crece de mayor a menor.

2. montón montón

El montón se utiliza principalmente para la asignación de memoria dinámica y la memoria solicitada por la función malloc() está en el montón.

 El tamaño del montón abierto es 0x00000200 (512 bytes), el nombre es HEAP, NOINIT significa sin inicialización, con capacidad de lectura y escritura, y alineación de 8 bytes. __heap_base representa la dirección inicial del par y __heap_limit representa la dirección final del montón.

2.2 Tabla de vectores

La tabla de vectores es una matriz WORD (entero de 32 bits), cada subíndice corresponde a una excepción y el valor del elemento del subíndice es la dirección de entrada del ESR. Se puede establecer la ubicación de la tabla de vectores en el espacio de direcciones, y la dirección de la tabla de vectores se indica a través de un registro de reubicación en el NVIC. Después del reinicio, el valor de este registro es 0. Por lo tanto, se debe incluir una tabla de vectores en la dirección 0 (es decir, la dirección 0 de FLASH) para la asignación de excepciones durante la inicialización. Vale la pena señalar que aquí hay una alternativa: el tipo 0 no es una dirección de entrada, sino el valor inicial del MSP después del reinicio, que se explicará en detalle más adelante.

Línea 55: defina un segmento de código, el nombre del segmento es RESET y READONLY significa solo lectura.

Líneas 56-58: use EXPORTAR para declarar los 3 identificadores a los que se hará referencia externamente y declare __Vectors, __Vectors_End y __Vectors_Size para que tengan atributos globales.

Línea 60: __Vectors indica la dirección inicial del vector y DCD indica la asignación de un espacio de 4 bytes. Cada fila de DCD generará un código binario de 4 bytes y la tabla de vectores de interrupción almacena la dirección de entrada de la rutina de servicio de interrupción. Cuando ocurre una excepción (es decir, un evento de interrupción), el sistema de interrupción de la CPU asignará la dirección de entrada correspondiente al contador del programa de la PC y luego comenzará a ejecutar la rutina de servicio de interrupción. Después de la línea 60, se define a su vez la dirección de entrada de la rutina de servicio de interrupción.

 Línea 138: __Vectors_End es la dirección final de la tabla de vectores.

Línea 139: __Vectors_Size es el tamaño de la tabla de vectores, y el tamaño de la tabla de vectores se obtiene restando __Vectors de __Vectors_End.

2.3 Procedimiento de reinicio

El programa de reinicio es el primer programa que se ejecuta después de encender el sistema. El programa de reinicio también es un programa de interrupción, pero es especial, así que solo hablaré de él aquí.

Línea 145: Se define un programa de servicio y PROC indica el comienzo del programa.

Línea 146: Utilice EXPORTAR para declarar que Reset_Handler se referenciará externamente, seguido de [DÉBIL] para indicar una definición débil. Una función débilmente definida se puede redefinir en un archivo externo. En este caso, se utiliza la función definida en el archivo externo. Si el archivo externo no está definido, se hace referencia a la función [DÉBIL] definida aquí. Esto significa que el usuario puede volver a implementar el procedimiento de reinicio en otros archivos. Esta forma de escritura es muy común en la biblioteca HAL.

Líneas 147-148: se refieren a dos etiquetas de archivos externos, donde __main es una función de biblioteca C estándar, utilizada principalmente para inicializar la pila de usuario. Esto lo hace el compilador, y esta función eventualmente llamará a la función principal que escribimos para ingresar a nuestro sistema. SystemInit() es una función de biblioteca, utilizada principalmente para la configuración del reloj del sistema y la configuración relacionada con interrupciones.

Línea 149: Cargue la dirección de SystemInit de la memoria en el registro R0

Línea 150: salta a la dirección en R0 (es decir, la función SystemInit), y determina el estado del procesador de acuerdo con el LSE del registro, y guarda la dirección de la siguiente instrucción antes del salto a LR.

Líneas 151-152: igual que las dos líneas anteriores, cargue la dirección de __main desde la memoria en R0 y salte a la dirección en R0. La diferencia entre 152 y 150 es que después de que la línea 152 salte a la dirección del registro especificado, no volverá.

Línea 153: corresponde a PROC, indicando el final del programa.

2.4 Rutina de servicio de interrupción

Qué interrupción usar generalmente, solo necesita escribir el programa de servicio de interrupción correspondiente, pero estas funciones se omiten en el archivo de inicio, pero el contenido está vacío, el programa de servicio de interrupción real debe volver a implementarse en el archivo C externo , aquí está solo de antemano Acabo de tomar un lugar.

No hay necesidad de hablar sobre esta parte, similar al programa de servicio, solo preste atención a la declaración 'B.', B significa saltar, saltar a un '.' aquí, lo que significa bucle infinito. 

3. El proceso de ejecución del programa

El proceso de operación del programa de la microcomputadora de un solo chip se divide en varios pasos de obtención de instrucciones, análisis de instrucciones y ejecución de instrucciones.

(1) Obtención de instrucciones: lea la instrucción de la memoria del programa de acuerdo con el valor en la PC del contador del programa y envíela al registro de instrucciones.

(2) Analizar instrucciones: sacar el código de operación de la instrucción en el registro de instrucciones y decodificarlo, y analizar la naturaleza de la instrucción. Si la instrucción requiere un operando, busque la instrucción del operando.

(3) Ejecución de instrucciones: No es más que convertir un código binario en una señal digital (niveles alto y bajo), operar circuitos de puertas lógicas y realizar entradas y salidas como nuestro sumador. Emita el resultado de la operación de la puerta lógica y emita el nivel de pin relevante del microcontrolador alto o bajo.

El proceso de la computadora de un solo chip que ejecuta el programa es en realidad repetir el proceso de operación mencionado anteriormente uno por uno hasta que encuentra un comando de parada y puede esperar el comando en un bucle.

Por ejemplo:

Cuando se enciende, la computadora de la calculadora de programa se convierte en 0000H. Luego, la microcomputadora de un solo chip ingresa automáticamente al proceso de ejecución del programa bajo la acción del circuito secuencial. El proceso de ejecución es en realidad un proceso cíclico de obtención de instrucciones (obtención de la etapa de instrucción almacenada previamente en la memoria) y ejecución de instrucciones (análisis y ejecución de instrucciones).

Por ejemplo, ejecute la instrucción: MOV A,#0E0H, su código de máquina es 74H E0H, la función de esta instrucción es enviar el operando E0Hal acumulador, que 0000Hse ha almacenado en la unidad 74Hy 0001Hse ha almacenado en la unidad E0H. Cuando la microcomputadora de un solo chip comienza a funcionar, primero ingresa a la etapa de obtención de instrucciones, y la secuencia es:

  • El contenido del contador del programa (en este momento 0000H) se envía al registro de direcciones;

  • El contenido del contador del programa se incrementa automáticamente en 1 (se convierte en 0001H);

  • El contenido del registro de dirección ( 0000H) se envía a la memoria a través del bus de dirección interno, y el circuito decodifica la dirección en la memoria, de modo que 0000Hse selecciona la unidad con la dirección;

  • La CPU afirma la línea de control de lectura;

  • El contenido de la unidad de memoria seleccionada bajo el control del comando de lectura (debe ser 74H en este momento) se envía al bus de datos interno, porque es la etapa de obtención de instrucciones, por lo que el contenido se envía al registro de instrucciones a través del bus de datos.

4. Acceso a datos

Para el almacenamiento y lectura de instrucciones y datos durante la ejecución del programa de la microcomputadora de un solo chip, el entendimiento es el siguiente:

El segmento de código, el segmento .data, el segmento .bss y el segmento rodata del programa se almacenan en Flash. Una vez que se enciende la MCU, el código ensamblador de inicialización copia el segmento .data y el segmento .bss en la RAM, crea una pila y comienza a llamar a la función principal del programa.

Después de eso, hay memoria de programa y memoria de datos.Las instrucciones se leen desde Flash (es decir, memoria de instrucciones, memoria de código) en tiempo de ejecución, y los datos se leen y escriben desde RAM. El punto de RAM es ser más rápido.

Independientemente de si se trata de una microcomputadora de un solo chip o una PC, las pirámides de memoria existentes son consistentes.El factor de velocidad y la limitación de costos conducen a una velocidad más rápida y un costo más alto de la memoria más rápida. Cabe decir que la comprensión de ellos es la comprensión de la pirámide de la memoria.

Supongo que te gusta

Origin blog.csdn.net/panpan_jiang1/article/details/129678118
Recomendado
Clasificación