Programación de operaciones de memoria en lenguaje C integrado
Si te encanta la programación, ama el lenguaje C;
Si te encanta el lenguaje C, ama los punteros;
Si te encantan los punteros, ama los punteros. ¡Punteros que aman los punteros!
Este artículo habla principalmente sobre las habilidades relacionadas con las operaciones de memoria en la programación C de sistemas integrados. Domine y tenga un conocimiento profundo de los punteros de datos, los punteros de función, la aplicación dinámica de la memoria, las constantes y los punteros. palabras clave volátiles, etc. El conocimiento relevante es el requisito básico para un excelente programador en lenguaje C. Cuando dominamos firmemente las habilidades anteriores, habremos aprendido el 99% del lenguaje C, porque las connotaciones más esenciales del lenguaje C están en las operaciones de memoria. Reflexión. ¡El 99% de la razón por la que usamos el lenguaje C para programar en sistemas integrados es por sus poderosas capacidades de operación de memoria!
Puntero de datos
Programación en sistemas integrados. A menudo se requiere leer y escribir contenido en una unidad de memoria específica, y el ensamblado tiene las instrucciones MOV correspondientes. Sin embargo, otros lenguajes de programación distintos de C/C++ básicamente no tienen la capacidad de acceder directamente a direcciones absolutas durante la depuración real. En los sistemas integrados, a menudo es necesario utilizar punteros en lenguaje C que tienen la capacidad de leer y escribir el contenido de unidades de dirección absolutas. La manipulación directa de la memoria con punteros suele ocurrir en las siguientes situaciones:
(1) Un chip de E/S está ubicado en el almacenamiento del espacio de la CPU en lugar del espacio de E/S, y el registro corresponde a una dirección específica;
(2) Dos CPU se comunican con la RAM de doble puerto. La CPU debe estar en una unidad específica de la RAM de doble puerto (llamada buzón de correo) para escribir contenido y generar una interrupción en la CPU de la otra parte;
(3) Leer los caracteres chinos y las fuentes en inglés grabadas en una unidad específica de ROM o FLASH. Recuerde: la CPU se direcciona en bytes y los punteros del lenguaje C aumentan y disminuyen según la longitud del tipo de datos al que apuntan. Comprender esto es muy importante para operar la memoria con punteros.
Punteros de función
En primer lugar, comprenda las siguientes tres preguntas:
(1) El nombre de la función en lenguaje C corresponde directamente a la dirección en la memoria de el código de instrucción generado por la función, por lo que el nombre de la función se puede asignar directamente al puntero que apunta a la función;
(2) Llamar a una función es en realidad equivalente a "transferir instrucción + procesamiento de transferencia de parámetros + retorno posición para apilar". Esencialmente, la operación principal es asignar la primera dirección del código de destino generado por la función al registro de PC de la CPU;
(3) Porque la esencia de una llamada a función es para saltar al código de una determinada unidad de dirección para su ejecución, puede "llamar" a una entidad de función que no existe en absoluto
Matriz frente a aplicación dinámica
Aplicación de memoria dinámica Los requisitos en los sistemas integrados son más estrictos que la programación general del sistema. Esto se debe a que el espacio de memoria de los sistemas integrados suele ser muy limitado y las pérdidas de memoria inadvertidas pronto provocarán el colapso del sistema. que su malloc y free aparezcan en pares. Estos son los principios:
(1) Utilice matrices tanto como sea posible. No se puede acceder a las matrices fuera de los límites (la verdad es una falacia si está un paso más allá). los límites) Cruzar el límite completará gloriosamente un sistema integrado caótico);
(2) Si se utiliza una aplicación dinámica, se debe juzgar si la aplicación es exitosa después de la aplicación, y deberían aparecer malloc y free. en pares!
La palabra clave const
const significa "solo lectura". Es muy importante distinguir las funciones de los siguientes códigos. Después de años de lucha en el mundo. Solo se puede decir que es una tragedia:
const int a;
int const a;
const int *a; int * const a;
int const * a const;
(1) La función de la palabra clave const es transmitir un significado especial a las personas que leen su código. Por ejemplo, agregar la palabra clave const antes de un parámetro formal de una función significa que el parámetro no se modificará en el cuerpo de la función y es un "parámetro de entrada". Cuando hay varios parámetros formales, la persona que llama a la función puede confiar en los parámetros. Si hay una palabra clave const delante para identificar claramente cuáles son parámetros de entrada y cuáles son posibles parámetros de salida.
/p>
(2) El uso adecuado de la palabra clave const permite al compilador proteger de forma natural los parámetros que no se espera que cambien y evitar que sean modificados por código no intencionado, lo que puede reducir la aparición de errores.
Palabra clave volátil
El compilador del lenguaje C optimizará el código escrito por el usuario, como el siguiente código:
int a,b,c;
a = inWord(0x100); /*Lee el contenido del puerto 0x100 del espacio de E/S y guárdalo en una variable*/
b = a;
a = inWord (0x100) ; /*Lea el contenido del puerto 0x100 del espacio de E/S nuevamente y guárdelo en una variable*/
c = a;
Es probable que esté optimizado. por el compilador como:
int a,b,c;
a = inWord(0x100); /*Leer el contenido del puerto 0x100 en el espacio de E/S y almacenarlo en a variable*/
b = a;
c = a;
Sin embargo, dichos resultados de optimización pueden generar errores si el contenido de la E/S El puerto space 0x100 es leído por otros programas después de la primera operación de lectura. Escriba un nuevo valor, luego el contenido leído en la segunda operación de lectura es en realidad diferente al de la primera vez, y los valores de b y c deberían ser diferentes. Agregar la palabra clave volátil antes de la definición de la variable a puede evitar optimizaciones similares por parte del compilador. El enfoque correcto es:
volatile int a;
Las variables volátiles se pueden usar en las siguientes situaciones :
(1) Registros de hardware de dispositivos paralelos (como: Registro de estado, el código en el ejemplo pertenece a esta categoría);
(2) Una variable no automática ( es decir, una variable global) a la que se accederá en una subrutina de servicio de interrupción;
( 3) Variables compartidas por varias tareas en aplicaciones multiproceso.