Solo especifica “un sistema incrustado”. Es raro que dos sistemas integrados sean exactamente iguales, por lo general no lo son, por lo que para responder correctamente a su pregunta, tendré que responder en términos muy generales que son comunes a la mayoría de los sistemas integrados. Otros han dado algunas respuestas que serían correctas para un sistema embebido específico , pero no correctas para todos los sistemas embebidos.
Al encender o reiniciar el sistema, dependiendo del microprocesador / microcontrolador exacto utilizado, comenzará a ejecutar código desde una dirección fija en la memoria que está integrada en el hardware del chip, o con otros irá a una dirección incorporada específica para lea la dirección en la que comienza su firmware. La mayoría de los procesadores que conozco hacen uno u otro, pero puede haber otros que usen otro método diferente. Una cosa importante para recordar acerca de los sistemas embebidos es que generalmente son más diferentes entre sí que similares.
Lo siguiente depende del idioma en el que escribió su código. Hablaré solo sobre los 2 idiomas de sistema embebido más comunes, lenguaje ensamblador y C.
- ¿El boom de IOT creará muchos trabajos integrados?
- ¿Qué tan útil es BITS Work Integrated Learning Programme (WILP) para M.Tech Embedded Systems en términos de ganar exposición?
- Seré entrevistado para el puesto de desarrollador de Embedded OS. ¿Qué preguntas pueden hacer?
- ¿Cuáles son los pros y los contras de la interfaz I2C versus SPI?
- ¿Cuáles son los enfoques de diseño basados en modelos disponibles para desarrollar aplicaciones integradas?
Con C, lo primero que debe ejecutarse es el código de “inicio de C” que el compilador insertó allí. Algunos llaman a esto el archivo “C-cero” porque su nombre de archivo es a menudo c0.asm, está escrito en lenguaje ensamblador y está completamente generado por el compilador. El código de “inicio de C” ejecuta y realiza cualquier inicialización de variables globales que puedan ser necesarias (generalmente a un valor de cero), y configura el sistema de asignación de memoria dinámica (que le permite usar malloc () y free ()). Esto es una simplificación de lo que sucede, y puede haber más dependiendo del procesador específico utilizado y el compilador específico utilizado, pero lo que he descrito es común a todas las rutinas de “inicio C”.
Al final de la rutina “C startup”, el código se bifurca a la primera instrucción ejecutable en su función C “main ()”.
Si el código fue escrito en lenguaje ensamblador, entonces no hay una rutina de “inicio C”, usted como programador tiene el control completo desde la primera instrucción leída por el procesador.
En cualquier caso, el programador necesita escribir código que primero inicializará todos los periféricos internos y externos, configurando todo el hardware a un estado conocido para que esté listo para su uso. Si hay que realizar cualquier otra inicialización específica del proyecto, generalmente se realiza inmediatamente después de la inicialización del hardware.
Un “periférico interno” muy común, y uno de los más importantes, es el “árbol de reloj” del procesador, que a menudo debe configurarse para seleccionar la frecuencia de funcionamiento deseada (el reloj del sistema) y cómo se llega a esa frecuencia (divida el reloj de cristal por alguna cantidad, o use un PLL – Phase Locked Loop – para multiplicar el reloj de cristal hacia arriba por alguna cantidad). Algunos procesadores no tienen configuración de reloj y solo funcionarán a una velocidad fija determinada por el cristal del reloj, y en el otro extremo del espectro, algunos otros procesadores tienen procedimientos de configuración de reloj muy complejos. Pero si el reloj del sistema requiere configuración, será lo primero que debe hacer el código, ya sea lo primero en “main ()”, si su lenguaje es C, o lo primero que haga en su código de lenguaje ensamblador.
Después de completar todas las inicializaciones de hardware, luego debe inicializar todas las variables, estructuras, etc., que pueden necesitar inicialización a algunos valores conocidos.
Después de que todo esto se haya completado, es tradicional que la mayoría de los sistemas integrados ingresen en un “ciclo permanente” (a menudo denominado “ciclo principal”) que nunca sale (excepto, por supuesto, en el ciclo de encendido o reinicio). El código incrustado no se ejecuta como un “programa” tradicional en el que, una vez hecho, la ejecución del código vuelve al sistema operativo. La mayoría de las veces un sistema embebido (especialmente los más pequeños) no tiene ningún sistema operativo (estos se denominan sistemas “bare metal”), porque lo que necesitan hacer es tan simple que simplemente no se necesita un O / S. Mientras la energía permanezca encendida y no haya reinicio, el procesador continuará ciclando a través del “bucle principal” para siempre. Es este bucle el que realiza llamadas a las funciones en el orden requerido para realizar las tareas que el sistema integrado está destinado a realizar.
A veces, un sistema integrado utilizará un RTOS (Sistema operativo en tiempo real) que permitirá y administrará la multitarea en su código (los programadores de escritorio los llaman “hilos”, pero han sido llamados “tareas” en los sistemas integrados para muchos , muchas décadas, son esencialmente lo mismo).
Y algunos sistemas embebidos usan un “O / S tradicional”, siendo el más común algún “sabor” de Linux, generalmente un Linux con un “núcleo en tiempo real” (no de escritorio o Linux Raspberry Pi, que no tiene ” núcleos en tiempo real “) porque uno de los atributos importantes de un sistema integrado es el determinismo, lo que significa que el ingeniero que diseña el sistema integrado y su firmware siempre puede determinar con anticipación cuánto tiempo llevará exactamente cualquier operación. Un O / S tradicional sin un núcleo en tiempo real se ejecuta de una manera no determinista y, por lo tanto, no es adecuado para sistemas embebidos donde el tiempo de todas las operaciones debe garantizarse y conocerse en el momento del diseño.
Más allá de eso, el sistema integrado está ejecutando el código que se escribió para cumplir con el trabajo que el sistema estaba destinado a hacer.
Y de eso se trata lo que es más común para la mayoría de los sistemas integrados al inicio.