Diferencia entre __I y __IO y __O en el núcleo de CMSIS

en el archivo de encabezado core_cm4.h definido algo como esto:

#ifdef __cplusplus
  #define   __I     volatile             /*!< Defines 'read only' permissions                 */
#else
  #define   __I     volatile const       /*!< Defines 'read only' permissions                 */
#endif
#define     __O     volatile             /*!< Defines 'write only' permissions                */
#define     __IO    volatile             /*!< Defines 'read / write' permissions              */

¿Cuál es la diferencia entre __I, __O y __IO mientras se definen de la misma manera?

  • ¿Y cómo funcionan para especificar " solo lectura/escritura " mientras que solo se definen como una variable volátil?
¿Convenio de denominación? Creo que la palabra clave que estás buscando es " const volátil ".

Respuestas (3)

"I" significa: Entrada

"O" significa: Salida

"IO" significa: Entrada y Salida

Como señala Long Pham, es una convención de nomenclatura, pero también es normal usar significados para un tipo. Al igual que un número entero, puede ser un contador, una marca de tiempo, una fecha, etc.

Hay algunas razones para usar esto:

  • Es bueno para la legibilidad.
  • Siempre que en el futuro cambie el tipo de I, O o IO, no es necesario cambiar el código fuente (usuario) que usa I, O e IO, solo las definiciones de tipo / se definen a sí mismas.
Sin embargo, no explica por qué usan un conmutador de compilador de C++ diferente. Creo que los límites de C++ son la razón principal por la que, para empezar, inventaron estos calificadores caseros.
@Lundin Yo también lo creo, me concentré en las diferencias de E/S/IO con respecto a la denominación

Dado que esto es para la definición de un mapa de registro de hardware:

Creo que la razón es que C, a diferencia de C++, permite la declaración de constvariables calificadas sin proporcionar un inicializador:

volatile const uint32_t REG; // Ok in C, invalid in C++

Del mismo modo, C ++ tampoco permite que constlos miembros de struct/classes no se inicialicen. Esto es un inconveniente cuando tenemos registros de hardware de solo lectura y deseamos hacer un mapa de registros usando estructuras (clases).

Es probable que esta limitación del lenguaje C++ sea la razón por la que este encabezado usa un truco sucio #ifdef __cpluspluspara eliminar constde un registro que debería haberse constcalificado.

Solo uno de los muchos pequeños detalles que hacen que C++ sea menos adecuado que C para la programación relacionada con el hardware.

Este archivo de encabezado también se creó para admitir c ++,

Por lo tanto, en el caso de la variable const de C , se indica como constante y el usuario no puede modificarla. Sin embargo, el compilador de C no realiza ninguna optimización adicional para esta variable const .

Pero en el caso de C++, esta variable constante puede ser reemplazada por el valor constante asignado a esa variable.

En el caso de que las variables miembro de la estructura de c ++ no estén optimizadas, por lo tanto, const se puede usar allí.

Por lo tanto, este archivo de encabezado proporciona __I,__O, __IO para las variables escalares y
__IM,__OM,__IOM para los miembros de la estructura.

No entiendo ni estoy de acuerdo con esta explicación. ¿Qué quiere decir con "sin más optimización"? Eso no está especificado por ningún estándar, los compiladores pueden hacer lo que les plazca. ¿Y qué diablos tiene eso que ver con los mapas de registro? Espero que algún compilador de C++ chiflado no reemplace mi variable de registro de hardware de solo lectura con una constante entera.
@Lundin "sin más medios de optimización" en C, la variable 'const' se tratará como una variable cuyo valor no puede ser modificado en el código por el usuario y, en segundo plano, no se reemplazará por su valor directamente en el código. Cada operación de lectura accederá a la dirección de la variable por su valor. En este caso, el compilador asignará memoria para esta variable en la sección Texto.
@Lundin Los mapas de registro deben definirse con 'Volátil' y 'const' según el tipo de registro. Por ejemplo, supongamos que tenemos un registro de salida de conversión ADC que he asignado a una variable. Ahora, para un programa mejor, robusto y libre de errores, queremos que la variable sea de solo lectura para que no se escriba accidentalmente. Por lo tanto, const nos ayuda aquí. Y también queremos que cada operación de lectura profundice y obtenga el valor de la ubicación de la memoria, no del búfer de lectura/escritura (esto puede ocurrir en caso de una configuración de optimización alta durante la compilación). Por lo tanto, la volatilidad ayuda en este caso.